Hello and welcome to our community! Is this your first visit?
Register
Enjoy an ad free experience by logging in. Not a member yet? Register.
Page 1 of 2 12 LastLast
Results 1 to 15 of 16
  1. #1
    New to the CF scene
    Join Date
    Jun 2014
    Posts
    2
    Thanks
    0
    Thanked 0 Times in 0 Posts

    Object Instantiation with immediate functions

    Hello! First post here!

    I thought i had a pretty good understanding of JavaScript but as the Dunning-Kruger effect would have it I was asked a question that I thought I could answer but started to confuse myself in the process.

    Which of the following ways is "best practice" to instantiate an object without polluting the global scope? The first (CountObject) only puts the return value in the global scope while the second (CountObject2) puts the whole function in the global scope.

    My assumption is CountObject is the more appropriate way if the goal is to keep the global context as concise as possible and truly hide the implementation but I can't really attest to any performance hits one might encounter in a real world scenario.

    Code:
    var CountObject = (function () {
        function countObject() {
            this._a = 1;
            this._b = 2;
            this._c = this._a + this._b;
        }
    
        return function () {
            var cobject = new countObject();
            this.add = function(num) {
                return cobject._c = cobject._a + cobject._b + cobject._c + num;
            }
        }
    }());
    
    var CountObject2 = function() {
        var a = 1;
        var b = 2;
        var c = a + b;
    
        return {
            add : function(num) {
                return c = a + b + c + num;
            }
        }
    }
    
    var textObject1 = new CountObject();
    
    console.log(textObject1.add(1));
    
    console.log(textObject1.add(1));
    console.log(textObject1.add(1));
    
    var testObject2 = new CountObject();
    
    console.log("testobject2:" + testObject2.add(100));
    
    
    var testObject3 = new CountObject2();
    console.log("testobject3: " + testObject3.add(100));
    
    var testObject4 = new CountObject2();
    console.log("testobject4: " + testObject4.add(100));
    
    console.log(window.CountObject);
    console.log(window["CountObject2"]);

    The output is as follows:

    Code:
    7 test.js:30
    11 test.js:32
    15 test.js:33
    testobject2:106 test.js:37
    testobject3: 106 test.js:41
    testobject4: 106 test.js:44
    
    function () {
            var cobject = new countObject();
            this.add = function(num) {
                return cobject._c = cobject._a + cobject._b + cobject._c + num;
            }
        } test.js:46
    ---------------------------------------------------added to separate 
    function () {
        var a = 1;
        var b = 2;
        var c = a + b;
    
        return {
            add : function(num) {
                return c = a + b + c + num;
            }
        }
    
    
    } test.js:47

    Any opinions/corrections?

    Thanks!

  • #2
    Senior Coder rnd me's Avatar
    Join Date
    Jun 2007
    Location
    Urbana
    Posts
    4,349
    Thanks
    11
    Thanked 589 Times in 570 Posts
    the first one is slower because it uses an extra closure in the local name lookup chain, and takes the time to publish the internal state.
    my site (updated 13/9/26)
    BROWSER STATS [% share] (2014/5/28) IE7:0.1, IE8:5.3, IE11:8.4, IE9:3.2, IE10:3.2, FF:18.2, CH:46, SF:7.9, NON-MOUSE:32%

  • #3
    Master Coder felgall's Avatar
    Join Date
    Sep 2005
    Location
    Sydney, Australia
    Posts
    6,640
    Thanks
    0
    Thanked 649 Times in 639 Posts
    To remove the entire JavaScript from the global namespace simply wrap the entire code inside of

    Code:
    (function() {
    // all your script goes here
    })();

    The only time anything needs to be global is where you are using a library supplied in a separate file and need to pass the single variable that references the library in the global space to get it from one file to the other.
    Stephen
    Learn Modern JavaScript - http://javascriptexample.net/
    Helping others to solve their computer problem at http://www.felgall.com/

    Don't forget to start your JavaScript code with "use strict"; which makes it easier to find errors in your code.

  • #4
    Senior Coder rnd me's Avatar
    Join Date
    Jun 2007
    Location
    Urbana
    Posts
    4,349
    Thanks
    11
    Thanked 589 Times in 570 Posts
    Quote Originally Posted by felgall View Post
    To remove the entire JavaScript from the global namespace simply wrap the entire code inside of

    Code:
    (function() {
    // all your script goes here
    })();
    only in "use strict" is that the case: implicit (accidental) globals, side-effects, eval-spawning, and explicit publishing can all occur inside a function...
    on a side note, we also need globals for jsonp, event attributes, and polyfills, not just libs. i'm not saying you're way-off, just liberal in your use of "only time".
    my site (updated 13/9/26)
    BROWSER STATS [% share] (2014/5/28) IE7:0.1, IE8:5.3, IE11:8.4, IE9:3.2, IE10:3.2, FF:18.2, CH:46, SF:7.9, NON-MOUSE:32%

  • #5
    Master Coder felgall's Avatar
    Join Date
    Sep 2005
    Location
    Sydney, Australia
    Posts
    6,640
    Thanks
    0
    Thanked 649 Times in 639 Posts
    Quote Originally Posted by rnd me View Post
    only in "use strict" is that the case: implicit (accidental) globals, side-effects, eval-spawning, and explicit publishing can all occur inside a function...
    on a side note, we also need globals for jsonp, event attributes, and polyfills, not just libs. i'm not saying you're way-off, just liberal in your use of "only time".
    Well jsonp and polyfills are usually provided by a separate "library" script and there is no such thing as event attributes - there are event handlers and event listeners and both can be included entirely within your script although you can have clashes with other scripts if you use event handlers.

    I agree about your point regarding "use script"; but who writes JavaScript these days without using that command (other than people who haven't kept up to date with how to write JavaScript and they don't even know what scope is).
    Stephen
    Learn Modern JavaScript - http://javascriptexample.net/
    Helping others to solve their computer problem at http://www.felgall.com/

    Don't forget to start your JavaScript code with "use strict"; which makes it easier to find errors in your code.

  • #6
    Senior Coder rnd me's Avatar
    Join Date
    Jun 2007
    Location
    Urbana
    Posts
    4,349
    Thanks
    11
    Thanked 589 Times in 570 Posts
    Quote Originally Posted by felgall View Post
    I agree about your point regarding "use scrict"; but who writes JavaScript these days without using that command (other than people who haven't kept up to date with how to write JavaScript and they don't even know what scope is).
    idiots like me who care about features, compatibility, and performance...

    i switch "use strict" on once in a blue moon if i'm having trouble during development, sort of like a built-in jslint, but i always switch it back off when i'm done debugging.
    i don't see the point of individual end-users using it to perform actual work, it just slows things down...

    this is just like how html validation is most useful to find problem-causing markup errors like missing close tags, but silly to do routinely in an HTML5 world.
    Last edited by rnd me; 06-13-2014 at 12:40 AM.
    my site (updated 13/9/26)
    BROWSER STATS [% share] (2014/5/28) IE7:0.1, IE8:5.3, IE11:8.4, IE9:3.2, IE10:3.2, FF:18.2, CH:46, SF:7.9, NON-MOUSE:32%

  • #7
    Master Coder felgall's Avatar
    Join Date
    Sep 2005
    Location
    Sydney, Australia
    Posts
    6,640
    Thanks
    0
    Thanked 649 Times in 639 Posts
    For freatures and compatibility you are better off to turn "use strict"; on as that is the more compatible version of JavaScript when it comes to future additions and making sure that commands are processed the way they are supposed to.

    I haven't noticed any performance issues with using it eiher - which browser is it where you have seen performance issues?
    Stephen
    Learn Modern JavaScript - http://javascriptexample.net/
    Helping others to solve their computer problem at http://www.felgall.com/

    Don't forget to start your JavaScript code with "use strict"; which makes it easier to find errors in your code.

  • #8
    Supreme Master coder! Philip M's Avatar
    Join Date
    Jun 2002
    Location
    London, England
    Posts
    18,017
    Thanks
    203
    Thanked 2,538 Times in 2,516 Posts
    https://developer.mozilla.org/en-US/...pe/Strict_mode


    Browsers don't reliably implement strict mode yet, so don't blindly depend on it. Strict mode changes semantics. Relying on those changes will cause mistakes and errors in browsers which don't implement strict mode. Exercise caution in using strict mode, and back up reliance on strict mode with feature tests that check whether relevant parts of strict mode are implemented. Finally, make sure to test your code in browsers that do and don't support strict mode. If you test only in browsers that don't support strict mode, you're very likely to have problems in browsers that do, and vice versa.

    All the code given in this post has been tested and is intended to address the question asked.
    Unless stated otherwise it is not just a demonstration.

  • #9
    Senior Coder rnd me's Avatar
    Join Date
    Jun 2007
    Location
    Urbana
    Posts
    4,349
    Thanks
    11
    Thanked 589 Times in 570 Posts
    Quote Originally Posted by felgall View Post
    For freatures and compatibility you are better off to turn "use strict"; on as that is the more compatible version of JavaScript when it comes to future additions and making sure that commands are processed the way they are supposed to.

    I haven't noticed any performance issues with using it eiher - which browser is it where you have seen performance issues?
    If your code works under "use strict" in development, passing tests and all that, how does removing the directive before production affect forward compatibility?

    I wouldn't go so far as to call it a performance problem, but nearly every test i've seen pegs "regular" js as fast or faster than strict mode. Given the relative simplicity of enabling this small speedup, it's worth it. But shipping under "use strict" can break code that could work older browsers without it (after debugging). It can break a whole concat'd script package if used globally, and it means you'll have two different versions of your app to maintain/test in production (w/support and without). I will say it is nice that "use strict" won't hurt anything going forward, and it might prevent noob mistakes, so it's not the worst thing ever. But i don't see it as a must-do at this point, or anything close. at best it's a wash between pros+cons+complications either way. if it delivered on the speed it promised years ago, my calculus would be different.
    Last edited by rnd me; 06-13-2014 at 08:55 AM.
    my site (updated 13/9/26)
    BROWSER STATS [% share] (2014/5/28) IE7:0.1, IE8:5.3, IE11:8.4, IE9:3.2, IE10:3.2, FF:18.2, CH:46, SF:7.9, NON-MOUSE:32%

  • #10
    New to the CF scene
    Join Date
    Jun 2014
    Posts
    2
    Thanks
    0
    Thanked 0 Times in 0 Posts
    So unless I am using the Chrome profiler incorrectly, it looks like this code:

    Code:
    var CountObject = (function () {
        function countObject() {
            this._a = 1;
            this._b = 2;
            this._c = this._a + this._b;
    
            countObject.prototype.add = function(num) {
                return this._c = this._a + this._b + this._c + num;
            }.bind(this);
        }
    
        return function () {
            var cobject = new countObject();
            this.add = cobject.add;
        }
    }());
    Is faster and has a slightly smaller memory footprint than this:

    Code:
    var CountObject2 = function () {
        var a = 1;
        var b = 2;
        var c = a + b;
    
        return {
            add : function(num) {
                return c = a + b + c + num;
            }
        }
    }
    But that seems counterintuitive to me...

  • #11
    Master Coder felgall's Avatar
    Join Date
    Sep 2005
    Location
    Sydney, Australia
    Posts
    6,640
    Thanks
    0
    Thanked 649 Times in 639 Posts
    Quote Originally Posted by rnd me View Post
    If your code works under "use strict" in development, passing tests and all that, how does removing the directive before production affect forward compatibility?
    It doesn't since code that runs with use strict is a subset of what will run without it. The purpose of the command is to provide a way to discard the commands that are no longer a part of JavaScript so that they no longer run while still providing a way for antiquated scripts using long obsolete commands to run as well (given that there are lots of really old scripts out there that use commands no longer a part of JavaScript.

    Provided you are writing current JavaScript and not using obsolete commands whether or not you actually include that statement makes no difference to what the commands do.

    Quote Originally Posted by rnd me View Post
    But shipping under "use strict" can break code that could work older browsers without it (after debugging).
    The only time use strict can break code in older browsers is if you leave off the quotes to hide the command from browsers that don't understand it. All the command does is to delete commands from the language that were deprecated long ago and should not have been used after Netscape 4 died out and to redefines some commands to the safe subset of what they used to be allowed to do.

    If you apply use strict to the wrong scope then that can break antiquated scripts attached to the page but they will break during testing - there is nothing different about how JavaScript runs between your test and live environments - they are both just web pages at different web addresses.

    At least that's how it is supposed to work and I have never come across any currently valid JavaScript code that works differently in browsers depending on whether use strict is being applied or not. I can understand that some older browsers that support use strict may have slight performance issues which you can do away with by removing the statement after you finish testing but it shouldn't have any effect on whether the code in the page still runs or not as you still need to use feature sensing to check if the commands introduced to JavaScript in 2011 are supported or not regardless of whether you are using use strict to enforce that long dead JavaScript commands can't be used.

    If you have an example of where applying use strict to a page that works at one address but which breaks at another address where an antiquated browser that doesn't understand the command (and so treats it as a text string not being assigned to anything and which can therefore simply be discarded) is being used, please share it. I'd be interested to see what you have found that the standards failed to take into account.
    Stephen
    Learn Modern JavaScript - http://javascriptexample.net/
    Helping others to solve their computer problem at http://www.felgall.com/

    Don't forget to start your JavaScript code with "use strict"; which makes it easier to find errors in your code.

  • #12
    Senior Coder rnd me's Avatar
    Join Date
    Jun 2007
    Location
    Urbana
    Posts
    4,349
    Thanks
    11
    Thanked 589 Times in 570 Posts
    RE: "The only time use strict can break code in older browsers..." :

    Code:
    function biggest(min){  
     "use strict";
     min= +min || 0; 
     return Math.max.apply(Math, arguments);
    }
    
    var a, b=-5, c=1/10;
    biggest(a,b,c);
    In IE7/8/9 (and others), it returns 0.1, and in Chrome, Firefox et al, it returns NaN.
    take out the "use strict", and the code runs the same everywhere.

    common? no, but most hard-to-debug problems aren't...

    i will happliy concede that the particular example might not be broken, depending on what you want from the function.
    My main point is that different output from the same input to a pure function (assuming we left out the Math.max) is utter BS.
    Last edited by rnd me; 06-13-2014 at 11:05 PM.
    my site (updated 13/9/26)
    BROWSER STATS [% share] (2014/5/28) IE7:0.1, IE8:5.3, IE11:8.4, IE9:3.2, IE10:3.2, FF:18.2, CH:46, SF:7.9, NON-MOUSE:32%

  • #13
    Master Coder felgall's Avatar
    Join Date
    Sep 2005
    Location
    Sydney, Australia
    Posts
    6,640
    Thanks
    0
    Thanked 649 Times in 639 Posts
    Quote Originally Posted by rnd me View Post
    In IE7/8/9 (and others), it returns 0.1, and in Chrome, Firefox et al, it returns NaN.
    take out the "use strict", and the code runs the same everywhere.
    Interesting example - I wonder why IE7/8/9 (and others) return the wrong answer.

    I can't see how getting rid of the "use strict" that IE7/8/9 don't recognise anyway would change the result in those browsers so I assume you mean that getting rid of the statement results in all browsers returning the wrong answer - given that your example code updates the value of min but does not update arguments[0] which the standard defines as being the value originally passed as the first parameter and once you change min the two fields are not supposed to be the same any more.

    To fix the obscure bug you have in that code you could rewrite it as:

    Code:
    function biggest(){  
     "use strict";
     arguments[0]= +arguments[0]; 
     return Math.max.apply(Math, arguments);
    }
    
    var a, b=-5, c=1/10;
    biggest(a,b,c);
    then all browsers would produce the same result of 0.1

    Anyway this is NOT an example of having tested the code across all of the browsers and getting the same result in each while testing and then getting a different result once the code goes live. It is an example of a change that was made between antiquated and modern JavaScript where you have identified that the code is not written correctly according to the modern JavaScript standards. If you are writing modern rather than antiquated code then you'd fix the code so it works across all browsers before the page goes live rather than reverting back to antiquated code.

    Do you have an example that doesn't rely on browsers not following the current standards?
    Stephen
    Learn Modern JavaScript - http://javascriptexample.net/
    Helping others to solve their computer problem at http://www.felgall.com/

    Don't forget to start your JavaScript code with "use strict"; which makes it easier to find errors in your code.

  • #14
    Senior Coder rnd me's Avatar
    Join Date
    Jun 2007
    Location
    Urbana
    Posts
    4,349
    Thanks
    11
    Thanked 589 Times in 570 Posts
    Quote Originally Posted by felgall View Post
    Do you have an example that doesn't rely on browsers not following the current standards?
    no, i don't think that's an issue at all, the problem i'm referring to is caused by fragmented legacy device support. it's nice that several years ago the spec became more clear on arg/param binding, even outside of strict mode. Now that that and other ambiguity was removed, there are only dozens of differences out there between JS cores instead of hundreds. will they make "use strict" the default one day? i hope not, and if they don't, then "use strict" has the same future compatibility profile as "regular" JS, provided you don't plan on bugs sticking around...

    Mozilla describes it best:
    Strict mode in browsers
    Browsers don't reliably implement strict mode yet, so don't blindly depend on it. Strict mode changes semantics. Relying on those changes will cause mistakes and errors in browsers which don't implement strict mode. Exercise caution in using strict mode, and back up reliance on strict mode with feature tests that check whether relevant parts of strict mode are implemented. Finally, make sure to test your code in browsers that do and don't support strict mode. If you test only in browsers that don't support strict mode, you're very likely to have problems in browsers that do, and vice versa.
    https://developer.mozilla.org/en-US/...de_in_browsers
    Last edited by rnd me; 06-14-2014 at 12:35 AM.
    my site (updated 13/9/26)
    BROWSER STATS [% share] (2014/5/28) IE7:0.1, IE8:5.3, IE11:8.4, IE9:3.2, IE10:3.2, FF:18.2, CH:46, SF:7.9, NON-MOUSE:32%

  • #15
    Senior Coder rnd me's Avatar
    Join Date
    Jun 2007
    Location
    Urbana
    Posts
    4,349
    Thanks
    11
    Thanked 589 Times in 570 Posts
    Quote Originally Posted by powerworks View Post
    So unless I am using the Chrome profiler incorrectly, it looks like this code:
    ... Is faster and has a slightly smaller memory ...
    But that seems counterintuitive to me
    how are you testing that with the chrome profiler?
    i ask because my results with the profiler tend to jump around a bit, even on back to back runs, so "slightly" might not mean anything more than noise.

    you could likely make the first one a clear winner by moving the add method outside of the countObject() function.
    removing the bind would help in V8 as well for some reason. you don't need it, even inside the constuctor because as a method, "this" means the instance anyway. prebinding only makes the method non-applicable to other objects at no gain.
    Even though it seems like binding this would help reduce run-time work, i've notice a clear perf hit on bound functions, and you don't need it and can't use it once you move the method out of the constructor.

    in terms of what you got going now:
    consider that that the first add method is pure, which lets the JS engine prove it can be recycled on any instance, but the second one uses private closures, so it cannot be shared among instances. see Compile time function execution for more nerdy details.
    my site (updated 13/9/26)
    BROWSER STATS [% share] (2014/5/28) IE7:0.1, IE8:5.3, IE11:8.4, IE9:3.2, IE10:3.2, FF:18.2, CH:46, SF:7.9, NON-MOUSE:32%


  •  
    Page 1 of 2 12 LastLast

    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
    •