JavaScript VS Java

按:熟悉 Java 后,再接触 JavaScript,实在很不容易丢掉从 Java 带过来的习惯和偏见。JavaScript 最让人恼火的就是名字中有 Java 但其实又和 Java 完全不一样,这个名称,让 Java 用户觉得 JavaScript 和 Java 很类似,因为同为类 C 的语法,JavaScript 确实很容易上手,但稍微一深入使用,又发现和 Java 的诸般不同,Java 的经验反成了障碍,就生了很强的挫折感。花了一点时间阅读 Douglas Crockford 的《JavaScript 语言精粹》,终于有了一些重要的体会。

相异

对象

JavaScript 和 Java 都和"对象"有关系. JavaScript 中所有对象都基于一个叫 Object 对象, 他的继承是通过对象继承对象, 而在 Java 中, 对象的创建, 必须通过类来完成. Java 中有所谓的接口(interface), 虽然 Java 的类是单继承的, 但通过接口, 也就实现了多继承, 而 JavaScript 的继承是所谓的"原型继承", 没有多继承这个概念.

数组

JavaScript 中确实有一个 Array 内置对象,但此数组和 C, Java 中的完全不一样!

  • JavaScript 的数组其实是一个类似 Java 中的 map 结构,这个可以参考本站中案例《两个 for...in 程序》第一个例子。
  • JavaScript 的数组长度是任意的。
  • JavaScript 数组中的元素,类型可以是不一样的。不过 Java 中也可以突破这一点,那就是定义一个 Object[] 以包含所有类型的对象。

继承

JavaScript 用的是原型(prototype)继承,这是 Java 中完全没有的概念。其实原型继承比 Java 这种 OO 语言中的要简单很多。JavaScript 中没有类的概念,继承是在对象的基础上来继承的,这个被继承的对象,就是所谓的原型对象,原型对象也有被它继承的原型对象,在继承关系的最顶端,是内置对象 Object,这个和 Java 中的根类 Object 有些类似。

var A = {}; // 一个对象在被创建时,如果没有指定原型对象,它的原型对象就是默认的 Object.

var B.prototype = A; // 设置 B 的原型为 A, 即实现了 B 从 A 继承,就这么一句就搞定了继承,这个比 Java 简单多了——从类继承了,还要 new 一个对象才能用。

在原型继承中,每个对象都有一个原型对象,不同对象可以从同一个原型继承。

同名函数(方法)

JavaScript 中识别函数或方法,仅仅依据函数名,和返回类型,参数个数,参数类型都没关系,这点和 Java 这种很“精确”的语言就很不一样了。JavaScript 是弱类型的语言,所以不能通过返回类型和参数类型来区分函数。至于为什么不用参数个数来区分函数,估计和 JavaScript 的字面量特性有关系,函数(方法)本质上仍然是对象的一个属性,函数名就是属性名,属性名相同的话,就认为是同一个属性,具体值,就是最后一个定义的。

        var o = {
            fa : function(a) {
                alert("a")
            },
            fa : function(a, b) {
                alert("a b")
            }
        };
        o.fa();

以上,根据执行结果,可以看到执行的是第二个函数。

闭包

这个特性是 JavaScript 而 Java 没有的。简单说就是函数中再定义函数,还是基于 JavaScript 的字面量特性和函数本身可以作为返回值有关。

直接可用的东西

在 JavaScript 中,直接可以使用的,有元数据类型和内置对象,而 Java 中只能使用元数据类型,别无所谓的内置对象。

变量的作用域

在 JavaScript 中,并不推荐延迟定义的做法,它的变量作用域是函数级别的:在函数中任意位置定义的变量,作用域都是整个函数可见。一般推荐将所有变量定义在函数开头。

相似

参数封装

这是一个编程实践上的技巧。当方法的参数太多时,JavaScript 可以通过 json 对象将参数封装起来。这点类似于 Java 对参数的 DTO 方式的封装。(TODO: 这部分可以写的详细一些,举一个例子说明如何封装和使用更好,隔了一年多再过来看,有些不清楚了)