【问题标题】:Variable caching in JavaScript vs. other languagesJavaScript 与其他语言中的变量缓存
【发布时间】:2012-02-28 18:17:59
【问题描述】:

最近有人告诉我这很糟糕:

var el = $("#myID");
$(el).addClass("a");
$(el).addClass("b");
$(el).addClass("c");

并且它应该像这样被缓存:

var $el = $("#myID");
$el.addClass("a");
$el.addClass("b");
$el.addClass("c");

所以,我的问题是,为什么不自动优化?在 Java 和其他语言中,我认为编译器足够聪明,可以自己进行缓存。

也就是说,这个:

// myList is a List<String>
String str = myList.get(0);
String trimmed = str.trim();
String sub = str.substring(0, 5);
boolean abc = str.startsWith("abc");

没有比这更有效的:

String trimmed = myList.get(0).trim();
String sub = myList.get(0).substring(0, 5);
boolean abc = myList.get(0).startsWith("abc");

任何了解编译器的人都可以在这里给我一些见解吗? JavaScript 就这么愚蠢吗?或者对于 Java/其他也是如此?

【问题讨论】:

  • 虽然编译器可能有足够的信息来推断函数是纯的(此外,它并不依赖于 DOM - 它需要更多信息,例如知道在调用之间没有发生 DOM 操作,这已经失控了),很少有人真正尝试过。 Java 编译器是故意愚蠢的,而 JIT 编译器(用于 Java 和 JS)更受编译时间的限制。他们通常坚持不需要大量分析的最有利可图的优化(例如,推测性地删除虚拟调用,或者在 JS 中为某些变量假定静态类型)。
  • 如果你关心简洁,使用jquery的语法糖:$("#myID").addClass("a").addClass("b").addClass("c"); 这样你的代码就不必维护这个变量了,它会更快地超出范围。
  • @bert 是的,显然......这只是一个玩具示例。

标签: java javascript caching compiler-construction


【解决方案1】:

$(el) 是一个相对昂贵的函数调用。编译器无法知道每次调用都会返回相同(或至少是等效的)对象,因此无法进行您建议的优化。

这不一定是语言的功能。我确信会有一些语言(也许你可以将函数声明为幂等),其中编译器可以推理返回值并进行优化。

我很确定 Java 编译器/优化器可以在相对简单的情况下做到这一点。

因此,对于同样简单的情况,Javascript 编译器没有理由在适当的情况下不这样做。但值得考虑的是,编译是在浏览器中进行的,因此您希望花在优化上的 CPU 时间可能会受到限制,以免影响用户的浏览体验。

【讨论】:

  • 听起来你的回答是“也许 JS 会优化,但不要依赖它。”
  • 很不错的概要。没有理由不应该在简单的情况下或者如果它准备好努力工作。但是,特别是对于这个 jQuery 函数调用,我怀疑它是否会成功。
  • 如果您愿意,还有一个问题...编译器函数内联是一种进行这种优化的方法吗?如果是这样,是否只有纯函数才是内联的候选对象?
【解决方案2】:

你认为编译器比实际更聪明!

请记住,编译器只知道语言的语法和语义,而不知道 API 的约定。因此,即使您可能知道$(el) 将始终是同一个对象,编译器所知道的只是“使用参数el 调用$ 函数”,它不能假设该函数将返回相同的给定相同参数的值。 (例如考虑Math.random() 函数。)同样,从您的Java 示例中,我们可能知道myList.get(0) 将始终是同一个对象(通常,除非发生其他事情,对吧?)但编译器不能。

所以是的,存储对从函数调用中检索到的对象的引用并对该引用进行操作而不是重复调用函数确实更有效。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-11-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-04-03
    • 2011-12-15
    • 2016-12-24
    • 2022-01-07
    相关资源
    最近更新 更多