We might be able to stop using goog.bind in favor of some other pattern, but as 
you learned, the compiler must be able to generate the same closure instance 
for any class instance method when passed in as a parameter or stored in a 
variable (and maybe some other scenarios).

It is probably possible to come up with other schemes, but the scheme should 
probably handle scenarios in legacy code where addEventListener and 
removeEventListener get called more than once on the same AS closure.

HTH,
-Alex

On 1/5/22, 9:27 AM, "Harbs" <harbs.li...@gmail.com> wrote:

    Oh. I think I understand.

    removeEventListener needs to reference the same function as 
addEventListener which needs to be unique to an instance but match on 
subsequent checks.

    That’s what I was missing.

    Never mind, and sorry for the noise… ;-)

    Although, I wonder if there’s some way we can optimize “one time” event 
listeners…

    Harbs

    > On Jan 5, 2022, at 7:15 PM, Harbs <harbs.li...@gmail.com> wrote:
    > 
    > FWIW, I think the reason the goog version is so complicated is because it 
supports partially applying arguments when you first use goog.bind (which is 
not something we’re doing).
    > 
    > But I definitely would like to hear why it’s important for two bound 
methods to be equivalent. I’m probably missing something, but I can’t see where 
it would matter.
    > 
    > Caching the closure seems like it just adds bulk to instances and make an 
app use more memory.
    > 
    > Probably the most common use case of Language.closure is for event 
listeners. If the event listener is transient, it can be cleaned up by garbage 
collection. If it’s cached to the instance, it’ll live for the life of the 
instance. Seems like a down-side to me.
    > 
    > Harbs
    > 
    >> On Jan 5, 2022, at 6:37 PM, Harbs <harbs.li...@gmail.com 
<mailto:harbs.li...@gmail.com>> wrote:
    >> 
    >> On normal modern systems it’s roughly quivalent to this:
    >> 
    >> function(fn, selfObj, var_args){
    >>  return /** @type {!Function} */ (fn.call.apply(fn.bind, arguments));
    >> }.apply(null,arguments);
    >> 
    >> 
    >> Here’s the code:
    >> 
    >> goog.bindNative_ = function(fn, selfObj, var_args) {
    >>   return /** @type {!Function} */ (fn.call.apply(fn.bind, arguments));
    >> };
    >> 
    >> goog.bind = function(fn, selfObj, var_args) {
    >>   // TODO(nicksantos): narrow the type signature.
    >>   if (Function.prototype.bind &&
    >>       // NOTE(nicksantos): Somebody pulled base.js into the default 
Chrome
    >>       // extension environment. This means that for Chrome extensions, 
they get
    >>       // the implementation of Function.prototype.bind that calls 
goog.bind
    >>       // instead of the native one. Even worse, we don't want to 
introduce a
    >>       // circular dependency between goog.bind and 
Function.prototype.bind, so
    >>       // we have to hack this to make sure it works correctly.
    >>       Function.prototype.bind.toString().indexOf('native code') != -1) {
    >>     goog.bind = goog.bindNative_;
    >>   } else {
    >>     goog.bind = goog.bindJs_;
    >>   }
    >>   return goog.bind.apply(null, arguments);
    >> };
    >> 
    >> Not sure why you’d want to use two applies and one bind instead of a 
single apply in:
    >> 
    >> return function() {
    >>    return fn.apply(object, arguments);
    >>  };
    >> 
    >>> Did you test this with your chsnges:
    >>> 
    >>> var f1:Function = myInst.method;
    >>> var f2:Function = myInst.method;
    >>> 
    >>> trace(f1 == f2)
    >> 
    >> 
    >> No I didn’t. You’re right that will likely fail. But why is that 
important?
    >> 
    >> Thanks,
    >> Harbs
    >> 
    >>> On Jan 5, 2022, at 5:00 PM, Greg Dove <greg.d...@gmail.com 
<mailto:greg.d...@gmail.com>> wrote:
    >>> 
    >>> I would assume that goog.bind would be optimized by gcc if it can be
    >>> (perhaps it is inlined if it uses es5 function.protoype.bind 
internally- I
    >>> did not look inside it)
    >>> 
    >>> The function naming/caching in Language.closure is important, including
    >>> private naming conventions when they are needed for closures.
    >>> 
    >>> Did you test this with your chsnges:
    >>> 
    >>> var f1:Function = myInst.method;
    >>> var f2:Function = myInst.method;
    >>> 
    >>> trace(f1 == f2)
    >> 
    > 


Reply via email to