Javascript Lambda函数vs绑定,内存!(和性能)

Javascript Lambda函数vs绑定,内存!(和性能),javascript,lambda,bind,Javascript,Lambda,Bind,我想确定等效解决方案之间的最佳实践。用例是侦听事件的类的实例。Axel Rauschmayer博士的可读性。我同意他的看法。但是在性能和内存消耗方面,哪一个是最好的 使用lambda函数 如果垃圾收集器无法清除局部变量(此处el),是否有人可以确认或确认?或者,现代浏览器是否能够检测到它们在闭包中未被使用 与: 没有内存问题,但所有的基准测试都表明,bind比闭包慢得多(例如) 编辑:我不同意忽视bind性能问题的评论。我建议阅读Chrome中的实现代码。它不可能是有效的。我坚持认为:all我看

我想确定等效解决方案之间的最佳实践。用例是侦听事件的类的实例。Axel Rauschmayer博士的可读性。我同意他的看法。但是在性能和内存消耗方面,哪一个是最好的

使用lambda函数 如果垃圾收集器无法清除局部变量(此处
el
),是否有人可以确认或确认?或者,现代浏览器是否能够检测到它们在闭包中未被使用

与: 没有内存问题,但所有的基准测试都表明,
bind
比闭包慢得多(例如)

编辑:我不同意忽视
bind
性能问题的评论。我建议阅读Chrome中的实现代码。它不可能是有效的。我坚持认为:all我看到的基准测试在all浏览器上显示了类似的结果

有没有一种方法可以同时获得低内存使用率和良好的性能?

闭包(或箭头函数,又名lambdas)不会导致内存泄漏 如果垃圾收集器无法清除局部变量(此处
el
),是否有人可以确认或确认?或者,现代浏览器是否能够检测到它们在闭包中未被使用

,现代JavaScript引擎能够检测父作用域中的变量,这些变量在闭包中可见,但未使用。我找到了证明这一点的方法

步骤1:闭包使用10MB的变量 我在Chromium中使用了以下代码:

class Abc {
    constructor() {
        let arr = new Uint8Array(1024*1024*10) // 10 MB
        let el = document.getElementById("my-btn")
        if (el)
            el.addEventListener("click", ev => this.onClick(ev, arr))
    }
    onClick(ev) {
        console.log("Clicked!", ev.target)
    }
}

new Abc()
请注意
Uint8Array
类型的变量
arr
。它是一个10兆字节大小的文件。在第一个版本中,变量
arr
用于闭包

然后,在Chromium的开发者工具选项卡“Profiles”中,我拍摄了一个堆快照:

通过减小大小进行排序后,第一行是:“system/JSArrayBufferData”,大小为10 MB。这是我们的变量
arr

步骤2:10 MB的变量在闭包中可见,但未使用 现在我只需删除这行代码中的
arr
参数:

            el.addEventListener("click", ev => this.onClick(ev))
然后,第二个快照:

第一排已经消失了

这一经验证实了垃圾收集器能够清除活动闭包中可见但未使用的父作用域中的变量。

关于
Function.prototype.bind
我引用有关箭头功能的部分:

切勿调用
f.bind(this)
goog.bind(f,this)
(并避免写入
const self=this
)。所有这些都可以用箭头函数表达得更清楚,更不容易出错。这对于回调尤其有用,回调有时会传递意外的附加参数

谷歌明确建议使用lambdas而不是
Function.prototype.bind

相关的:

  • 来自Axel Rauschmayer博士


语法没有性能。实现确实如此。因此答案只能是“视情况而定”。由于jsPerf中的闭包示例在测试中的速度要快得多(无论如何,在Firefox中),我倾向于建议有一种优化方法,可以完全消除调用,这在实际代码中可能不可用。我建议事件委派以减少绑定的数量,使用逻辑对对象中的方法中的事件进行操作。我知道这与OP的要求不符,但我认为这是一个值得考虑的问题。仅供参考,根据您的示例,您可以实际执行
el.addEventListener(“单击”,this)
,然后给您的类一个
handleEvent
方法。当事件发生时,将调用
handleEvent
。这些功能实际上是等效的吗?在绑定版本中,可以通过“this”在事件处理程序中访问Abc实例,而在lambda版本中则不能。因此,如果需要访问实例,我将使用bind。如果只需要EVET.TAR(我的BTN元素),我通常更喜欢LAMBDA。如果只是确认没有问题,请考虑一般确认。现代GC实现在睡眠中处理这些问题。
class Abc {
    constructor() {
        let arr = new Uint8Array(1024*1024*10) // 10 MB
        let el = document.getElementById("my-btn")
        if (el)
            el.addEventListener("click", ev => this.onClick(ev, arr))
    }
    onClick(ev) {
        console.log("Clicked!", ev.target)
    }
}

new Abc()
            el.addEventListener("click", ev => this.onClick(ev))