FunctionExpression's and memory consumptions

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • kangax

    FunctionExpression's and memory consumptions

    There's a common pattern of "forking" a returning function as in the
    following example:

    function bind(fn, context) {
    var args = Array.prototype .slice.call(arg uments, 2);
    if (args.length) {
    return function() {
    fn.apply(contex t, args);
    }
    }
    return function() {
    return fn.call(context );
    }
    }

    The runtime speed benefits are obvious, but I've been told that there
    is an increased memory consumption in such cases. Are there 2 Function
    objects created when `bind` is being called? I assume that's not the
    case, since those are not FunctionDeclara tion's, but rather
    FunctionExpress ion's (and so they should not be evaluated foremost
    when execution context is entered). Are FunctionExpress ion's contained
    within blocks that are never evaluated create Function objects? Does
    it make a difference if FunctionExpress ion is contained within a
    `return` clause?

    I can't find relevant parts in the specification and would appreciate
    any insights on this matter.

    --
    kangax
  • dhtml

    #2
    Re: FunctionExpress ion's and memory consumptions

    kangax wrote:
    There's a common pattern of "forking" a returning function as in the
    following example:
    >
    function bind(fn, context) {
    var args = Array.prototype .slice.call(arg uments, 2);
    if (args.length) {
    return function() {
    fn.apply(contex t, args);
    }
    }
    return function() {
    return fn.call(context );
    }
    }
    >
    The runtime speed benefits are obvious, but I've been told that there
    is an increased memory consumption in such cases. Are there 2 Function
    objects created when `bind` is being called? I assume that's not the
    case, since those are not FunctionDeclara tion's, but rather
    FunctionExpress ion's (and so they should not be evaluated foremost
    when execution context is entered). Are FunctionExpress ion's contained
    within blocks that are never evaluated create Function objects? Does
    it make a difference if FunctionExpress ion is contained within a
    `return` clause?
    >
    Unreached expressions should have no effect. We can see a call expression:-

    function unreachableExpr ession() {
    if(true) return;
    alert("Panic!!! I did not feature-test alert!");
    }

    And a return statement would also have no effect:-

    function unreachableStat ement() {
    if(true) return true;
    return false;
    }

    Each time that bind function is called, a new function is created, not
    two. If arguments.lengt h were 0, the second function expression would be
    returned, but would always err because fn would be undefined. You
    probably meant to check "if(arguments.l ength 2)".

    function f(){
    alert(this.type );
    }

    var e = bind(f, { sound: "elephant" });

    The second function does not need the args property, so creating an
    array would be unnecessary.

    function bind(fn, context) {
    var args;
    if (arguments.leng th 2) {
    args = Array.prototype .slice.call(arg uments, 2);
    return function() {
    fn.apply(contex t, args);
    }
    }
    return function() {
    return fn.call(context );
    }
    }

    Garrett


    --
    comp.lang.javas cript FAQ <URL: http://jibbering.com/faq/ >

    Comment

    • David Mark

      #3
      Re: FunctionExpress ion's and memory consumptions

      On Oct 26, 9:42 pm, kangax <kan...@gmail.c omwrote:
      There's a common pattern of "forking" a returning function as in the
      following example:
      >
      function bind(fn, context) {
        var args = Array.prototype .slice.call(arg uments, 2);
        if (args.length) {
          return function() {
            fn.apply(contex t, args);
          }
        }
        return function() {
          return fn.call(context );
        }
      >
      }
      >
      The runtime speed benefits are obvious, but I've been told that there
      is an increased memory consumption in such cases. Are there 2 Function
      objects created when `bind` is being called? I assume that's not the
      case, since those are not FunctionDeclara tion's, but rather
      FunctionExpress ion's (and so they should not be evaluated foremost
      when execution context is entered). Are FunctionExpress ion's contained
      within blocks that are never evaluated create Function objects? Does
      No.
      it make a difference if FunctionExpress ion is contained within a
      `return` clause?
      What is a return clause?

      Comment

      • kangax

        #4
        Re: FunctionExpress ion's and memory consumptions

        On Oct 26, 10:49 pm, dhtml <dhtmlkitc...@g mail.comwrote:
        kangax wrote:
        There's a common pattern of "forking" a returning function as in the
        following example:
        >
        function bind(fn, context) {
        var args = Array.prototype .slice.call(arg uments, 2);
        if (args.length) {
        return function() {
        fn.apply(contex t, args);
        }
        }
        return function() {
        return fn.call(context );
        }
        }
        >
        The runtime speed benefits are obvious, but I've been told that there
        is an increased memory consumption in such cases. Are there 2 Function
        objects created when `bind` is being called? I assume that's not the
        case, since those are not FunctionDeclara tion's, but rather
        FunctionExpress ion's (and so they should not be evaluated foremost
        when execution context is entered). Are FunctionExpress ion's contained
        within blocks that are never evaluated create Function objects? Does
        it make a difference if FunctionExpress ion is contained within a
        `return` clause?
        >
        Unreached expressions should have no effect. We can see a call expression:-
        >
        function unreachableExpr ession() {
        if(true) return;
        alert("Panic!!! I did not feature-test alert!");
        >
        }
        >
        And a return statement would also have no effect:-
        >
        function unreachableStat ement() {
        if(true) return true;
        return false;
        >
        }
        >
        Each time that bind function is called, a new function is created, not
        two. If arguments.lengt h were 0, the second function expression would be
        returned, but would always err because fn would be undefined. You
        probably meant to check "if(arguments.l ength 2)".
        >
        function f(){
        alert(this.type );
        >
        }
        >
        var e = bind(f, { sound: "elephant" });
        >
        The second function does not need the args property, so creating an
        array would be unnecessary.
        >
        function bind(fn, context) {
        var args;
        if (arguments.leng th 2) {
        args = Array.prototype .slice.call(arg uments, 2);
        return function() {
        fn.apply(contex t, args);
        }
        }
        return function() {
        return fn.call(context );
        }
        >
        }
        Thanks, Garrett.
        That makes much sense.

        So, as far as I understand, function expression in "unreached" block
        is no different than any other expression in "unreached" block (in a
        sense that it shouldn't be executed and so shouldn't allocate any
        memory). Does spec actually define such behavior (object
        initialization) or is it left up to an implementation?
        >
        Garrett
        >
        --
        comp.lang.javas cript FAQ <URL:http://jibbering.com/faq/>
        --
        kangax

        Comment

        • Jorge

          #5
          Re: FunctionExpress ion's and memory consumptions

          On Oct 27, 2:42 am, kangax <kan...@gmail.c omwrote:
          There's a common pattern of "forking" a returning function as in the
          following example:
          >
          function bind(fn, context) {
            var args = Array.prototype .slice.call(arg uments, 2);
            if (args.length) {
              return function() {
                fn.apply(contex t, args);
              }
            }
            return function() {
              return fn.call(context );
            }
          >
          }
          >
          The runtime speed benefits are obvious, but I've been told that there
          is an increased memory consumption in such cases. Are there 2 Function
          objects created when `bind` is being called? I assume that's not the
          case, since those are not FunctionDeclara tion's, but rather
          FunctionExpress ion's (and so they should not be evaluated foremost
          when execution context is entered). Are FunctionExpress ion's contained
          within blocks that are never evaluated create Function objects? Does
          it make a difference if FunctionExpress ion is contained within a
          `return` clause?
          >
          I can't find relevant parts in the specification and would appreciate
          any insights on this matter.
          >
          Note that that creates both a function and a closure: the context of
          "bind" that is saved in the closure occupies memory as well. But only
          the function that is returned is created.

          --
          Jorge.

          Comment

          • kangax

            #6
            Re: FunctionExpress ion's and memory consumptions

            On Oct 28, 12:25 am, David Mark <dmark.cins...@ gmail.comwrote:
            On Oct 26, 9:42 pm, kangax <kan...@gmail.c omwrote:
            [snip]
            it make a difference if FunctionExpress ion is contained within a
            `return` clause?
            >
            What is a return clause?
            Sorry, I meant to say - return statement.

            --
            kangax

            Comment

            • David Mark

              #7
              Re: FunctionExpress ion's and memory consumptions

              On Oct 28, 7:49 am, kangax <kan...@gmail.c omwrote:
              On Oct 26, 10:49 pm, dhtml <dhtmlkitc...@g mail.comwrote:
              >
              >
              >
              kangax wrote:
              There's a common pattern of "forking" a returning function as in the
              following example:
              >
              function bind(fn, context) {
                var args = Array.prototype .slice.call(arg uments, 2);
                if (args.length) {
                  return function() {
                    fn.apply(contex t, args);
                  }
                }
                return function() {
                  return fn.call(context );
                }
              }
              >
              The runtime speed benefits are obvious, but I've been told that there
              is an increased memory consumption in such cases. Are there 2 Function
              objects created when `bind` is being called? I assume that's not the
              case, since those are not FunctionDeclara tion's, but rather
              FunctionExpress ion's (and so they should not be evaluated foremost
              when execution context is entered). Are FunctionExpress ion's contained
              within blocks that are never evaluated create Function objects? Does
              it make a difference if FunctionExpress ion is contained within a
              `return` clause?
              >
              Unreached expressions should have no effect. We can see a call expression:-
              >
              function unreachableExpr ession() {
                 if(true) return;
                 alert("Panic!!! I did not feature-test alert!");
              >
              }
              >
              And a return statement would also have no effect:-
              >
              function unreachableStat ement() {
                 if(true) return true;
                 return false;
              >
              }
              >
              Each time that bind function is called, a new function is created, not
              two. If arguments.lengt h were 0, the second function expression would be
              returned, but would always err because fn would be undefined. You
              probably meant to check "if(arguments.l ength 2)".
              >
              function f(){
                 alert(this.type );
              >
              }
              >
              var e = bind(f, { sound: "elephant" });
              >
              The second function does not need the args property, so creating an
              array would be unnecessary.
              >
              function bind(fn, context) {
                 var args;
                 if (arguments.leng th 2) {
                   args = Array.prototype .slice.call(arg uments, 2);
                   return function() {
                     fn.apply(contex t, args);
                   }
                 }
                 return function() {
                   return fn.call(context );
                 }
              >
              }
              >
              Thanks, Garrett.
              That makes much sense.
              >
              So, as far as I understand, function expression in "unreached" block
              is no different than any other expression in "unreached" block (in a
              sense that it shouldn't be executed and so shouldn't allocate any
              memory). Does spec actually define such behavior (object
              initialization) or is it left up to an implementation?
              Yes, it is defined in the specs, which you should be read at least
              once.

              Comment

              • Conrad Lender

                #8
                Re: FunctionExpress ion's and memory consumptions

                On 2008-10-30 06:54, dhtml wrote:
                I see that "The Good Parts" calls "FunctionDeclar ation" a "function
                Statement". This is completely misleading and I've been seeing posts
                using this wrong terminology a lot lately.
                This isn't just coming from The Good Parts.
                Mozilla uses it in their docs, too:


                Microsoft use it as well...
                The function declaration creates a binding of a new function to a given name.


                ....as does Flanagan in the "Definitive Guide":

                This is wrong terminology. What he is calling a function Statement is
                really a FunctionDeclara tion. A FunctionDeclara tion is not a
                Statement. It cannot appear where statements do.
                Most current implementations allow nesting:

                if (blah) {
                function blimm () {
                ....
                }
                }

                Mozilla treats this as a function expression, not a function
                declaration, meaning that it will not be evaluated unless blah is true.
                Only source elements will be treated as function declarations.
                An implementation that evaluated the function on either pass would
                seem to be doing whatever is the opposite of an optimization.
                Pessimization :-)


                - Conrad

                Comment

                • Richard Cornford

                  #9
                  Re: FunctionExpress ion's and memory consumptions

                  On Oct 30, 11:19 am, Conrad Lender wrote:
                  On 2008-10-30 06:54, dhtml wrote:
                  >
                  >I see that "The Good Parts" calls "FunctionDeclar ation" a
                  >"function Statement". This is completely misleading and
                  >I've been seeing posts using this wrong terminology a
                  >lot lately.
                  >
                  This isn't just coming from The Good Parts.
                  Mozilla uses it in their docs, too:
                  <snip>
                  Microsoft use it as well...
                  <snip>
                  ...as does Flanagan in the "Definitive Guide":
                  <snip>

                  Poor terminology choices are normal for both Flanagan and Microsoft,
                  and Mozilla documentation is still a little short of being good
                  (though certainly much improved over recent years). However, much
                  writing on the subject of javascript is (where it is not actually
                  inaccurate) aimed at audiences who have a great deal to learn before
                  they appreciate the subtleties; where moving in the direction of
                  understanding might be seen more productive than laying out the gory
                  details in full.

                  <snip>
                  Most current implementations allow nesting:
                  >
                  if (blah) {
                  function blimm () {
                  ....
                  }
                  >
                  }
                  >
                  Mozilla treats this as a function expression,
                  Not it does not.
                  not a function declaration, meaning that it will not be
                  evaluated unless blah is true.
                  With a function expression with optional Identifier (which is what the
                  above would be if it were a function expression) the resulting
                  function object can only be referenced using that Identifier from
                  inside the body of the function (all else being equal), because an new
                  object is added to the new function object's [[Scope]] and the
                  Identifier used to create a named property of that object to refer to
                  the function. Thus - blimm - is out of scope in the surrounding code,
                  if the code were a function expression.

                  In Mozilla browsers the function does become available using the
                  Identifier - blimm - in the containing scope, thus this is not a
                  function expression. In fact it is a function statement; a syntax
                  extension that is capable of allowing the conditional creation of a
                  function because being a Statement it can be evaluative inside a
                  block.

                  Mozilla also has FunctionDeclara tions (which create function objects
                  during variable instantiation) and FunctionExpress ions (which create
                  function object when evaluated, and do follow the ECMAScript rules
                  regarding optional Identifiers). The Mozilla docs might blur the
                  distinction but it exists regardless.

                  IE browsers also process the above code successfully (or at lest
                  without erroring) , but they see the function as a FunctionDeclara tion
                  regardless of its 'illegal' context. Thus IE would create a function
                  object during variable instantiation, and so any surrounding
                  conditions (the - if(blah){ ... } - in this case) become redundant,
                  and the last FunctionDeclara tion with any given name becomes the only
                  one available in the scope.

                  Most browsers (more or less) imitate one of these 'extensions' for
                  reasons of compatibility. But notations of which they should be
                  compatible with (JScript or JavaScript(tm)) seem to change. As I
                  recall (and my memory may not be accurate on this point) Opera had
                  switched from following JScript to following JavaScript, which Safari
                  has switched from following JavaScript to following JScript.

                  Obviously with two distinct interpretations of this code structure,
                  and minor browsers not necessarily sticking to following one or the
                  other (plus some related bugs that introduce some more variation)
                  using this type of code structure is seriously ill-advised. With
                  results that that may appear to 'work', but maybe only by coincidence
                  and for the time being. Plus (and most importantly) conditional
                  creation of function objects is (and always has been) possible using
                  pure ECMAScript constructs (by assigning the results of evaluating
                  function expressions to variables declared in the containing scope).

                  Interestingly the draft ES 3.1 spec is trying to switch
                  FunctionDeclara tion to being a Statement. How that will work out
                  remains to be seen as the last draft I looked at (the one before the
                  current draft, which I haven't looked at yet) did not include any
                  processing or evaluation rules for their function statements (a bit of
                  an oversight as it makes the draft language non-viable as it stood).
                  Only source elements will be treated as function declarations.
                  <snip>

                  Only function declarations will be treated as function declarations
                  (in ES 3), Statements are SourceElements.

                  Richard.

                  Comment

                  • kangax

                    #10
                    Re: FunctionExpress ion's and memory consumptions

                    On Oct 30, 1:54 am, dhtml <dhtmlkitc...@g mail.comwrote:
                    [snip explanation]

                    Thanks for such thorough explanation.
                    I'll make sure to read specs better next time.
                    --
                    comp.lang.javas cript FAQ <URL:http://jibbering.com/faq/>
                    --
                    kangax

                    Comment

                    • Conrad Lender

                      #11
                      Re: FunctionExpress ion's and memory consumptions

                      On 2008-10-30 13:06, Richard Cornford wrote:
                      >if (blah) {
                      > function blimm () {
                      > ....
                      > }
                      >>
                      >}
                      >>
                      >Mozilla treats this as a function expression,
                      >
                      Not it does not.
                      [..]
                      In Mozilla browsers the function does become available using the
                      Identifier - blimm - in the containing scope, thus this is not a
                      function expression. In fact it is a function statement; a syntax
                      extension that is capable of allowing the conditional creation of a
                      function because being a Statement it can be evaluative inside a
                      block.
                      You're right, what I meant to say was Mozilla "treats it as if it were
                      a function expression of the form: var blimm = function () {...}".
                      Although it has the form of a function declaration, no function object
                      will be created during the variable instantiation phase. Only when the
                      function "statement" is evaluated will its identifier become available
                      in the current scope.

                      Should the term "function statement" be used to specifically refer to
                      this extension?
                      IE browsers also process the above code successfully (or at lest
                      without erroring) , but they see the function as a FunctionDeclara tion
                      regardless of its 'illegal' context.
                      [...]
                      Most browsers (more or less) imitate one of these 'extensions' for
                      reasons of compatibility. But notations of which they should be
                      compatible with (JScript or JavaScript(tm)) seem to change. As I
                      recall (and my memory may not be accurate on this point) Opera had
                      switched from following JScript to following JavaScript, which Safari
                      has switched from following JavaScript to following JScript.
                      It appears that only Mozilla doesn't see them as function declarations.
                      In this example:

                      function testFD() {
                      if (true) {
                      function blimm() { alert("true"); }
                      } else {
                      function blimm() { alert("false"); }
                      }
                      blimm();
                      }

                      Opera 9.61 alerts "false", same as IE and Safari. Konqueror (old 3.5.2
                      version) doesn't see blimm at all.
                      [..] using this type of code structure is seriously ill-advised.
                      Of course; I fully agree.
                      Interestingly the draft ES 3.1 spec is trying to switch
                      FunctionDeclara tion to being a Statement.
                      I didn't know that. Could make things... interesting.
                      >Only source elements will be treated as function declarations.
                      <snip>
                      >
                      Only function declarations will be treated as function declarations
                      (in ES 3), Statements are SourceElements.
                      Not all Statements are SourceElements. Mozilla will not treat a
                      "function declaration in a block" as a FunctionDeclara tion, because
                      it's nested, and thus not a SourceElement.


                      (a little further down)


                      - Conrad

                      Comment

                      • Lasse Reichstein Nielsen

                        #12
                        Re: FunctionExpress ion's and memory consumptions

                        Conrad Lender <crlender@yahoo .comwrites:
                        You're right, what I meant to say was Mozilla "treats it as if it were
                        a function expression of the form: var blimm = function () {...}".
                        Not exectly.
                        Although it has the form of a function declaration, no function object
                        will be created during the variable instantiation phase. Only when the
                        function "statement" is evaluated will its identifier become available
                        in the current scope.
                        Exactly. A "var" declaration would also declare the "blimm" variable
                        globally in the scope. As you say, that's not what happens. Mozilla
                        only declares blimm if you actually execute the function statement. It
                        really is different from both "var" and "function" declarations, since
                        it adds a variable to the scope AFTER it was initially created and
                        populated by the declarations.

                        /L
                        --
                        Lasse Reichstein Holst Nielsen
                        DHTML Death Colors: <URL:http://www.infimum.dk/HTML/rasterTriangleD OM.html>
                        'Faith without judgement merely degrades the spirit divine.'

                        Comment

                        • Jorge

                          #13
                          Re: FunctionExpress ion's and memory consumptions

                          On Oct 30, 10:49 pm, Conrad Lender <crlen...@yahoo .comwrote:
                          >
                          You're right, what I meant to say was Mozilla "treats it as if it were
                          a function expression of the form: var blimm = function () {...}".
                          Although it has the form of a function declaration, no function object
                          will be created during the variable instantiation phase. Only when the
                          function "statement" is evaluated will its identifier become available
                          in the current scope.
                          No no it's not so. Any function declaration inside an inner block is
                          considered an error and ignored (in Mozillas). See this thread:



                          --
                          Jorge.

                          Comment

                          • Conrad Lender

                            #14
                            Re: FunctionExpress ion's and memory consumptions

                            On 2008-10-31 08:21, Jorge wrote:
                            No no it's not so. Any function declaration inside an inner block is
                            considered an error and ignored (in Mozillas).
                            They're not ignored. Try the function in my previous post and see if you
                            get an alert.
                            I'm not sure how this is relevant - nothing in that thread suggests that
                            Mozilla discards function declarations in a block.


                            - Conrad

                            Comment

                            • Conrad Lender

                              #15
                              Re: FunctionExpress ion's and memory consumptions

                              On 2008-10-31 06:55, Lasse Reichstein Nielsen wrote:
                              >Although it has the form of a function declaration, no function object
                              >will be created during the variable instantiation phase. Only when the
                              >function "statement" is evaluated will its identifier become available
                              >in the current scope.
                              >
                              Exactly. A "var" declaration would also declare the "blimm" variable
                              globally in the scope. As you say, that's not what happens. Mozilla
                              only declares blimm if you actually execute the function statement. It
                              really is different from both "var" and "function" declarations, since
                              it adds a variable to the scope AFTER it was initially created and
                              populated by the declarations.
                              The difference between "var x = function ..." and "function x ..." can
                              be shown in an example:

                              function testFD1() {
                              print(delete blimm); // =true (blimm not declared)
                              if (1) {
                              function blimm() { alert("true"); }
                              }
                              }

                              function testFD2() {
                              print(delete blimm); // =false (blimm has DontDelete attribute)
                              if (1) {
                              var blimm = function() { alert("true"); }
                              }
                              }

                              Out of curiosity, does this difference have any practical consequences
                              other than the return value of 'delete'?


                              - Conrad

                              Comment

                              Working...