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) >> >