Lambda函数vs绑定,内存! (和表现) [英] Lambda functions vs bind, memory! (and performance)

查看:247
本文介绍了Lambda函数vs绑定,内存! (和表现)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想确定哪种是等效解决方案之间的最佳实践。用例是监听事件的类的实例。 Axel Rauschmayer博士



按尺寸减小排序后,第一行是:system / JSArrayBufferData with a大小为10 MB。它是我们的变量 arr



步骤2:10 MB的变量可见但在闭包中未使用



现在我只删除这行代码中的 arr 参数:

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

然后,第二个快照:





第一行已消失。



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



关于功能.prototype.bind



我引用 Google JavaScript样式指南,有关箭头功能的部分:


从不致电 f.bind(this) goog.bind(f,this)(并避免编写 const self =此)。使用箭头功能可以更清楚地表达所有这些并且更不容易出错。这对于回调特别有用,回调有时会传递意外的额外参数。


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



相关:







I would like to determine which is the best practice between equivalent solutions. The use case is an instance of a class that listen to an event. Dr. Axel Rauschmayer prefers the lambda for readability. I agree with him. But in term of performance and memory consumption, which is the best?

With a lambda function

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

Can someone to confirm or infirm if the local variables (here el) can't be cleared by the garbage collector? Or, are modern browsers capable to detect they are unused in the closure?

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

There is no memory issue, but all benchmarks suggest that bind is far slower than a closure (an example here).

EDIT: I don't agree with the comments that ignore the performance issue of bind. I suggest to read this answer with the code of the implementation in Chrome. It cannot be efficient. And I insist: all the benchmarks I saw, show similar results on all browsers.

Is there a way to have a low memory usage and a good performance at the same time?

解决方案

Closures (or arrow functions, aka lambdas) don't cause memory leaks

Can someone to confirm or infirm if the local variables (here el) can't be cleared by the garbage collector? Or, are modern browsers capable to detect they are unused in the closure?

Yes, modern JavaScript engines are able to detect variables from parent scopes that are visible from a closure but unused. I found a way to prove that.

Step 1: the closure uses a variable of 10 MB

I used this code in 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()

Notice the variable arr of type Uint8Array. It is a typed array with a size of 10 megabytes. In this first version, the variable arr is used in the closure.

Then, in the developer tools of Chromium, tab "Profiles", I take a Heap Snapshot:

After ordering by decreasing size, the first row is: "system / JSArrayBufferData" with a size of 10 MB. It is our variable arr.

Step 2: the variable of 10 MB is visible but unused in the closure

Now I just remove the arr parameter in this line of code:

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

Then, a second snapshot:

The first row has vanished.

This experience confirms that the garbage collector is capable to clean variables from parent scopes that are visible but unused in active closures.

About Function.prototype.bind

I quote the Google JavaScript Style Guide, section on arrow functions:

Never call f.bind(this) or goog.bind(f, this) (and avoid writing const self = this). All of these can be expressed more clearly and less error-prone with an arrow function. This is particularly useful for callbacks, which sometimes pass unexpected additional arguments.

Google clearly recommends to use lambdas rather than Function.prototype.bind.

Related:


这篇关于Lambda函数vs绑定,内存! (和表现)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆