2011-03-31 26 views
4

我只是通过this article上有名函数表达式读取,其与IE < = 8Javascript:分叉函数声明有效多少?

我很好奇一个特别的声明不兼容:

在web开发中的一个常见的模式是“叉“基于某种功能测试的功能定义,可实现最佳性能。

从他的页面中抽取的:

var contains = (function() { 
    var docEl = document.documentElement; 

    if (typeof docEl.compareDocumentPosition != 'undefined') { 
    return function(el, b) { 
     return (el.compareDocumentPosition(b) & 16) !== 0; 
    }; 
    } 
    else if (typeof docEl.contains != 'undefined') { 
    return function(el, b) { 
     return el !== b && el.contains(b); 
    }; 
    } 
    return function(el, b) { 
    if (el === b) return false; 
    while (el != b && (b = b.parentNode) != null); 
    return el === b; 
    }; 
})(); 

当我看到这个,我的第一反应是,这将是可怕的维护。以这种方式编写的代码实际上并不容易理解。

在这种情况下,可以写一个嵌套的函数,而不是在另一个函数中有条件地定义函数,然后在声明外函数后立即调用该函数。这会更长,但在我看来更容易理解(尽管我来自C/C++/Java)。

我更喜欢那些包含一些测试编号或解释这些函数在运行时会有所不同的答案。

+3

JavaScript确实是一种功能语言,因此返回函数的函数非常普遍。一旦你习惯了,像这样的东西变得可读性和易于在脑海中解析。 – 2011-03-31 22:09:47

+0

你是什么意思_“不容易理解”_。这非常合理。 – Raynos 2011-03-31 22:16:46

+0

@Matt Greer ** JavaScript不是一种功能语言。虽然它确实具有作为一级值的功能(并且还有闭包,尽管范围很广),这些功能可以被认为是功能性构建体*,这是关于相似性结束的地方。语法是“程序的”,在大多数情况下鼓励副作用,没有原生的'列表'类型,没有模式匹配,没有柯里(隐式或显式)等。 – 2011-03-31 22:26:54

回答

2

使用Javascript:分叉函数声明有效多少?

除非任何魔法优化与JIT /运行时间为“成本”一样调用任何函数来完成。函数只是通常存储在变量(或属性)中的对象。

如何,它返回一个专门功能对象是更“有效”的版本取决于因素,包括(但不限于):

  1. 的执行所产生的功能的次数( 1X =无增益)和
  2. 的分支与其他代码(取决于)和
  3. 的创造的“成本”之称的“成本”关闭(很便宜)

对于廉价分支或执行次数较少的“效率”会减少。如果有特定使用案例,那么基准为,您将有“答案”。

当我看到这个,我的直接反应是,这将是可怕的维持。以这种方式编写的代码实际上并不容易理解。

这个例子不一定做到公正,IMOHO是凌乱的其他原因。例如,我认为给匿名外部函数一个明确的名称 - 即使对于函数表达式也可以这样做 - 这将有助于更好地阐明意图。编写代码先清理。然后运行性能分析(基准)并根据需要进行修复。机会是“缓慢的部分”不会是最初预期的。其中一些“不容易理解”就是对这个构造不熟悉(不是试图暗示任何负面的东西) - 另一方面,我所知道的每种语言都有被滥用的特征有更清洁解决方案的案例。

在这种情况下,代替有条件定义另一个函数的外部函数被声明之后然后立即称为内的函数,一个可以写嵌套IFS的功能。这会更长,但在我看来更容易理解(尽管我来自C/C++/Java)。

再次,确切的情况是有点混乱,IMOHO。但是,JavaScript是而不是 C/C++/Java和C/C++/Java中不存在函数作为第一类值和闭包(这是一个小小的谎言,闭包可以模拟Java和最新C++支持某种形式的闭包AFAIK - 但我不使用C++)。

此构造因此不能与其他语言中看到过,因为不支持它容易(或全部)其他语言 - 它说,关于方法的生存能力没有(在JavaScript或其他地方)的总称。

我宁愿答案,其中包括有关这些功能将如何在运行时不同的一些测试号码或解释。

请参阅上文。


在顶部在所述加粗部分展开:

的功能是“只是一个对象”,即“应用”(读:调用)与(...)运算符。

function x() { 
    alert("hi") 
} 
x() // alerts 
window.x() // alerts -- just a property (assumes global scope above) 
a = {hello: x} 
a.hello() // alerts (still property) 
b = a.hello 
b() // alerts (still just a value that can be invoked) 

快乐编码。

+0

谢谢你的深思熟虑的解释。我应该在帖子中添加我正在同时学习Ruby on Rails。也许我只是习惯了RoR约定如何强调可读性和逻辑分离成最小片段(当事情变得太臃肿时重构)。 由于您列举的原因,我给出了答案,这些答案正是为了我的好奇心。我同意由于我对JS不熟悉,我可能会被这种表示法弄糊涂 - 没有采取任何冒犯行为。 – 2011-04-01 22:07:46

+0

所以我看到它的方式,分叉函数声明是一种速度改进技巧,类似于C中的程序集阻塞,Ruby中的程序集阻塞,以及许多语言中的for循环展开。我熟悉这些概念,但主要是在我寻求速度改进时使用它们。在C++中解密汇编块同样(通常)比试图破译用香草C++编写的相同逻辑更困难。这篇文章的目的是让我感觉我应该多久使用这种技术。它似乎比我提到的优化技术更普遍 – 2011-04-01 22:19:59

3

这是非常有效的。最后注意();。这将立即执行并将外部函数的结果分配给contains。每次使用函数contains时,它比执行基础逻辑要高效得多。

而不是每次检查被称为compareDocumentPosition存在,这是在代码第一次执行时完成一次。 compareDocumentPosition存在或不存在的事实不会改变,所以只检查一次是理想的。

1

提到的主要优点是速度。具有嵌套if s的单个函数意味着每次调用函数时都需要重新评估条件。但是,我们知道条件的结果永远不会改变。

如果您担心的可读性,一个类似效果可以更可读的方式来实现的:

var contains = (function() { 
    var docEl = document.documentElement; 
    if (typeof docEl.compareDocumentPosition != 'undefined') { 
     return contains_version1; 
    } else if (typeof docEl.contains != 'undefined') { 
     return contains_version2; 
    } else { 
     return contains_version3; 
    } 

    function contains_version1() { 
     ... 
    } 

    function contains_version2() { 
     ... 
    } 

    function contains_version3() { 
     ... 
    } 
})(); 

或者:

(function() { 
    var docEl = document.documentElement; 
    var contains = 
     typeof docEl.compareDocumentPosition != 'undefined' ? contains_version1 : 
     typeof docEl.contains != 'undefined' ? contains_version2 : 
     contains_version3; 

    function contains_version1() { 
     ... 
    } 

    function contains_version2() { 
     ... 
    } 

    function contains_version3() { 
     ... 
    } 

})(); 
0

这是比较奇怪的构造,如果你来了从纯C背景开始,但应该很容易将已知概念映射为C++/Java人。这个特定的示例本质上是具有抽象函数的实现基类,其中有3个派生类,它们针对不同的浏览器实施不同的实现。在这种情况下使用“if”或“switch”并不是C++和Java中最好的方法。

可能的组的这样的功能将被打包成一个“类”,在这种情况下,它会密切映射到与虚函数和每个浏览器的多个实现基类...