C#和Javascript中函数的区别是什么?

5

我正在学习Javascript,读到了函数是一等公民并且大多数作者都提到函数可以返回函数(也就是对象)并将它们作为参数传递给其他函数。

我相信这里面还有很多内容。那么C#中的函数和Javascript中的函数有什么不同呢?

在C#中,我可以说函数不是对象(没有方法、属性等),即使通过闭包(使用lambda表达式和委托),它们看起来像Javascript中的函数对象吗?

我觉得在C#中使用lambda表达式时,对于刚接触这门语言的人来说,这种区别变得有点模糊了。


5
C# 并没有函数 per se,它只有方法(以及委托/lambda,它们是方法引用)。话虽如此,你可以把委托称为 C# 版本的 JavaScript 匿名函数对象。 - BoltClock
1
@BoltClock:函数 vs. 方法 vs. 过程 vs. 子程序 vs. 诸如此类...老实说,我真的看不出它们之间有什么区别,如果不是更多的话... - user541686
@BoltClock:还有,哇,响应时间真快! - user541686
@Mehrdad,实际上没有什么区别,至少是在从VB到C#再到Javascript进行比较时。 - jcolebrand
2
@jcolebrand:是的,这就是我的意思。我的意思是你可以真的开始挑剔,比如说,“函数只是指针”,“过程只是一个通用名称”,“方法也有上下文指针”,“子程序是不是协程的过程”,等等,但这并不是一个有用的区分。(只是提到它,因为每当我问一个C++问题并说“std::find方法”时,人们会说“C++没有方法”,因为这只是术语...他们显然知道你的意思哈哈。) - user541686
2
还有委托 vs. Lambda vs. 内联函数 vs. 闭包 vs. 神知道什么...乐趣永不停歇 :) - user541686
5个回答

7
大多数作者认为在JavaScript中,“函数是一等公民”。但是在C#中,它们只是附加到类上的方法,因此并不是一等公民。方法委托(和lambda表达式)是特定类,用于使方法“像”一等公民。
这里的问题是,我尽可能地解释了它,而不是让你回去阅读Crockford的“JavaScript:精粹”之类的东西:
JavaScript比C#少得多。不要将您可以在C#中直接执行的操作与您可以(或无法)在JavaScript中执行的操作进行比较(反之亦然)。
那么为什么不是所有语言(或至少是C#)都有“一等公民函数”?答案通常很简单:因为这不是语言设计要求。但这在某种程度上是我的借口,因为显然他们现在已经添加了它。但是,如果没有人告诉您在未来的语言中包含它,您会吗?

记住的关键是:在C#中,函数(方法)必须附加到一个类上。在Javascript中不需要。原因在语言定义(规范)中。

此外,我应该补充一下有关对象创建的声明:

你可以用以下两种方式之一在javascript中创建一个新对象:

//using object syntax
var ob1 = { name: value, nestedFunction: function(){} };

或者

//using a function
function MyFunc(){
  var name = value;
  function nestedFunction(){}
}
var ob2 = new MyFunc();

在第二种情况下,我们使用函数声明对象,在第一种情况下,我们仅使用文字语法进行声明。
要在C#中执行相同的操作,我们必须创建一个新对象作为类:
MyClass ob1 = new MyClass(); //constructor is a member function of the class
public class MyClass {
  public MyClass() {
  }
  public void nestedFunction(){
  }
}

注意在Javascript中,我仍然需要定义被返回的方法。
好的,我想今晚就这样吧。

3
我不太同意... Predicate<int> pred = i => i % 2 == 0; 对我来说看起来确实像是一等公民函数... 只不过类型没有被推断出来罢了。但这也并没有什么区别... - user541686
3
在C#中无法执行闭包?请原谅,但是...什么鬼? - user541686
1
哦,显然委托可以作为闭包的资格。我更喜欢我的闭包看起来像 function(){ ... } :p 请注意,您可以在JavaScript中使用嵌套函数,因为它们是一等公民。 - jcolebrand
1
你之前有使用过C#吗?(或者Scheme?或者D?或者Haskell或C++11等等...)因为你对闭包的理解似乎与Javascript紧密相关...而且,你提到的并不是一个真正的闭包 - 它只是执行一个普通的代码块,简单明了。唯一的区别是它防止了全局命名空间的损坏,但这个想法本身与闭包没有关系 - 这只是一个JS的东西。命名空间与闭包完全无关。 - user541686
我故意吐了吐舌头。实际上,我还没有使用过D,但可能应该尝试一下。在C#中,我仍然很难理解闭包,可能是因为我习惯于javascript风格的闭包。但是,我知道我可以像在Javascript中一样将数据嵌套到Func<T>中的function(){} - jcolebrand
显示剩余2条评论

3
JavaScript函数可以被创建并分配给一个变量,它们是语言中的一等公民,并且在应用C#所应用的语法糖方面具有更多的灵活性。
在C#中,当你编写代码:
x => x * x
编译器会创建一个真正的命名方法并将该方法包装在一个可执行的delegate中。
Delegates和C#应用的语法糖给人们带来了非常相似的感觉,但内部实际上做了非常不同的事情。
在JavaScript中,您可以直接创建一个函数并将其分配给一个变量,而无需将其包装在任何其他结构中以启用操作。函数是JavaScript中的一等公民。

在C#中,编译器并不完全这样做。你还需要提到委托类型。 :-) - user541686
当上下文中有可用的委托类型时,它将使用推断出的委托类型。这归结为语法糖。 - Kevin McKelvin

1

我能想到的最大不同点就是在C#函数中,变量是在词法作用域下的,而在Javascript中,变量除了this以外都是在词法作用域下的,而this则是在动态作用域下的。

例如,在Javascript中,你可以这样说:

var foo = new Object();
foo.x = 0;
var bar = function() { this.x = 2; };  // first-class function... what's "this"?
foo.baz = bar;   // Now foo has a method called 'baz', which is 'bar'.
foo.baz();
alert(foo.x);   // Displays 2 -- 'this' magically refers to 'foo'!

尝试用C#编写这个。

或者实际上,别费心了--它没有任何意义。

为什么?因为在这里,this在词法上并不指代任何东西!它的含义是动态变化的,不像在C#中,它的含义仅取决于封闭类,而不是调用者本身。


1
你错了。在任何编程语言中,函数中使用的变量可能是自由变量(非局部)或绑定变量(局部)。在词法作用域语言中,函数的自由变量被解析为函数 定义时 父级范围内的变量。在动态作用域语言中,函数的自由变量被解析为函数 调用时 调用范围内的变量。this关键字不是自由变量。它有特殊规则。请参见以下问题 - Aadit M Shah
@AaditMShah:嗯,不,我很确定这是正确的...不确定你说的哪个部分是“错误”的,但正如我所提到的,this在JS中是动态作用域,其他变量是静态作用域。我也不知道你在这里所说的自由变量与绑定变量的区别,因为除了this之外,我没有看到任何“自由”变量,而我已经提到了它是动态的。 - user541686
谢谢,真的很有趣...我甚至不知道动态作用域存在。 - JD.
虽然 Jcolebrand 回答了这个问题的一部分,但我会将答案告诉你... 虽然你也指出了我需要关注的一些方面 :) - JD.
2
@JD。顺便说一句,这并不伤害我的感情:p~选择你认为最恰当的答案,你只能打一个勾。 - jcolebrand
1
谢谢,我总是担心会伤害到别人的感情 :) - JD.

0

我对JS和C#之间的区别有一些初步的想法:

1、JS是一种解释性语言,这意味着JS需要一个内置的ECMAScript解释器才能工作。而C#是一种编译型语言,这意味着C#代码将被编译为IL以便工作。

2、JS是一种动态类型语言,这意味着在定义变量时不需要指定变量类型。而C#是一种静态类型语言,这意味着需要指定变量的确切类型。

3、面向对象封装,在JS中,很多人说函数是第一类公民。通常,函数有两种用途:a)只是一个用于操作某些工作的函数;b)类和构造函数,使用它们可以实例化对象。而在C#中,函数是函数,应该属于类(或接口)。

4、面向对象继承,在JS中,我们使用原型来实现继承。而在C#中,我们严格使用类来实现继承。

5、面向对象多态,在JS中,根据我的了解,我们可以使用伪数组arguments来实现函数重载以模拟多态,这是一种折衷方案。而对于C#,多态性得到了完美体现。

6、在JS中,我们没有垃圾回收机制。而对于C#来说,有一个强大的垃圾回收机制。

也许有些想法不正确,欢迎提出建议。


1
问题是关于C#和Javascript函数语义上的区别,而不是两种语言的差异列表。 - Kirk Woll

0

为了澄清一些混淆的问题;

1) JavaScript确实是一种编译语言。代码在浏览器执行之前会被编译,而且速度很快!这就是为什么一些开发人员认为它是一种“解释性”语言。

2) C#没有JS中的函数,它有类方法。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接