Lambda函数vs绑定,内存!(和表现)

Pal*_*leo 23 javascript lambda bind

我想确定哪种是等效解决方案之间的最佳实践.用例是监听事件的类的实例.Axel Rauschmayer博士更喜欢lambda的可读性.我同意他的看法.但就性能和内存消耗而言,哪个最好?

具有lambda功能

class Abc {
  constructor() {
    let el = document.getElementById("my-btn")
    if (el)
      el.addEventListener("click", evt => this.onClick(evt))
  }
  onClick(evt) {
    console.log("Clicked!", evt.target)
  }
}
Run Code Online (Sandbox Code Playgroud)

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

Function.prototype.bind:

class Abc {
  constructor() {
    let el = document.getElementById("my-btn")
    if (el)
      el.addEventListener("click", this.onClick.bind(this))
  }
  onClick(evt) {
    console.log("Clicked!", evt.target)
  }
}
Run Code Online (Sandbox Code Playgroud)

没有内存问题,但所有基准测试表明它bind比闭包慢得多(这里的一个例子).

编辑:我不同意忽略性能问题的评论bind.我建议使用Chrome中的实施代码阅读此答案.它效率不高.我坚持认为:我看到的所有基准测试在所有浏览器上显示出类似的结果.

有没有办法在同一时间内使用低内存和良好的性能?

Pal*_*leo 21

闭包(或箭头函数,也称为lambdas)不会导致内存泄漏

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

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

第1步:闭包使用10 MB的变量

我在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()
Run Code Online (Sandbox Code Playgroud)

注意arr类型的变量Uint8Array.它是一个大小为10兆字节的类型化数组.在第一个版本中,变量arr用在闭包中.

然后,在Chromium的开发人员工具中,选择"个人档案",我会看一个堆快照:

快照1:变量<code>arr</code>.</p>

<h3>第2步:10 MB的变量可见但在闭包中未使用</h3>

<p>现在我只删除<code>arr</code>这行代码中的参数:</p>

<pre><code>            el.addEventListener(Run Code Online (Sandbox Code Playgroud)

然后,第二个快照:

快照2:闭包中没有使用变量<code>Function.prototype.bind</code></h1>

<p>我引用<a rel=Google JavaScript样式指南,箭头函数部分:

永远不要打电话f.bind(this)goog.bind(f, this)(并避免写作const self = this).使用箭头功能可以更清楚地表达所有这些并且更不容易出错.这对回调特别有用,回调有时会传递意外的附加参数.

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

有关: