[译]JavaScript需要类吗?

[译]JavaScript需要类吗?

原文:http://www.nczonline.net/blog/2012/10/16/does-javascript-need-classes/



译者注:在我长达一年的工作生涯中,我遇到过有人把构造函数称做类,还有人把对象字面量称做类.这比把火狐扩展叫成插件都令我*疼.下面是Brendan Eich给今年的jsconf.eu录制的视频,其中提到了类.



无论你喜欢还是不喜欢,ECMAScript 6中将会包含类(class)这个新东西了[1].在JavaScript中,对类的需求一直都有两极分化的趋势.有些人特别喜欢JavaScript中没有类,因为这和其他语言不同.另一方面,还有一些人厌恶JavaScript没有类,因为这和其他语言不同.那些从C++或Java转到JavaScript的人们最需要克服的一个心理障碍就是"JavaScript中没有类",有些人和我说过,这就是他们为什么不喜欢Javascript或者不继续深入学习Javascript的原因之一.

JavaScript从发明的那天起就没有真正的类,这使得从一开始就造成了混乱.有不少JavaScript书籍或文章中都讲到了类,就好像JavaScript中真的存在类一样.但其实,他们所说的类只是一些自定义的构造函数,这些函数可以用来构造一些自定义的引用类型.在JavaScript中,引用类型已经是最接近于类的东西了.下面的代码你应该已经很熟悉了:

function MyCustomType(value) {
    this.property = value;
}

MyCustomType.prototype.method = function() {
    return this.property;
};

很多时候,这种代码被解释为是声明了一个MyCustomType类.但实际上,该代码做的所有事情仅仅是声明了一个MyCustomType函数,配合new运算符可以用它创建一个引用类型MyCustomType的实例.该函数和其他的函数并没有什么本质的不同.因为其他自定义的函数也可以作为构造函数来使用.

这样的代码从表面上看起来根本不像是在定义一个类,被定义的构造函数和其原型对象上的方法似乎没有什么联系.如果是JavaScript新手,很可能会认为这是两段完全无关的代码.但实际上,这两段代码有非常紧密的联系,只是和其他语言中的类的写法相差甚远罢了.

更令人困惑的是,一旦谈到继承,大部分人想到的术语是子类和超类等等,这样的概念只有在存在真正的类的前提下才有意义.在JavaScript中,实现继承的代码同样是冗长的:

function Animal(name) {
    this.name = name;
}

Animal.prototype.sayName = function() {
    console.log(this.name);
};

function Dog(name) {
    Animal.call(this, name);
}

Dog.prototype = new Animal(null);
Dog.prototype.bark = function() {
    console.log("Woof!");
};

实现继承需要两个步骤,创建构造函数和重写原型对象,这样的代码非常混乱.

在第一版的《JavaScript高级程序设计》中,我使用过术语"类".但从我收到的反馈中看,这样写是很令人困惑的.所以在第二版中,我把所有的"类(class)"都替换成了"类型(type)".事实表明,使用"类型"这个术语可以减少很多的混乱.

可是,还有一个比较突出的问题:定义一个自定义类型的语法是冗长的,实现两个类型之间的继承会更加复杂.没有什么简单的方法可以调用一个属于超类型的方法.在目前看来,创建并管理一个自定义类型是件很痛苦的事,如果你不信,可以看看有下面有多少JavaScript框架使用了自己的定义自定义类型和继承的方法:

  • YUI – 用Y.extend()来实现继承.使用该方法会在子类型上添加一个"superclass"属性.[2]
  • Prototype – 用Class.create()和Object.extend()来处理对象和"类".[3]
  • Dojo – 使用dojo.declare()和dojo.extend().[4]
  • MooTools – 有一个自定义类型Class,可以用来定义和扩展"类".[5]

这么多的JavaScript框架都有自己的解决方案,这明显是非常混乱的.JavaScript开发者们需要一种更好的实现此功能的语法.

ECMAScript 6中的类其实并没有什么新东西,只是在你已经熟悉的模式上增加了一层语法糖.看看下面这个例子:

class MyCustomType {
    constructor(value) {
        this.property = value;
    }

    method() {
        return this.property;
    }
}

这个ECMAScript 6中的类定义其实就是本文上面那个MyCustomType例子的另一种写法.使用这种类创建的对象实例完全和使用构造函数创建的对象实例一样.唯一的区别就是前者拥有更紧凑的语法.下面看看继承的写法:

class Animal {
    constructor(name) {
        this.name = name;
    }

    sayName() {
        console.log(this.name);
    }
}

class Dog extends Animal {
    constructor(name) {
        super(name);
    }

    bark() {
        console.log("Woof!");
    }
}

在实际效果上这个例子也同样等同于前面那种继承的写法.只是复杂的实现步骤被一个简单的extends关键字代替了.在类定义中你还可以直接使用super(),无需明确指出超类型的构造函数.

ECMAScript 6中的类是基于你已经熟知的JavaScript模式.实现继承的原理还和以前一样(基于原型链,调用超类型的构造函数),方法添加在原型上,属性在构造函数中声明.真正的区别只有一个:你可以打更少的字.

所以,如果你现在仍然不赞同ECMAScript 6引入类这么个东西,你可以这么想,要引入的这个类不是什么新东西,也并没有从根本上改变JavaScript的工作机制.不过我个人更推荐使用关键字type而不是class.

那么JavaScript真的需要类吗?答案是不需要,但JavaScript的确需要一个更简洁的方法来创建自定义类型.这恰巧就是ECMAScript 6中的"类"正要做的.如果这个"类"能帮助来自其他语言的开发者们更容易的转向JavaScript,那么它就是好东西.

参考

  1. Maximally minimal classes (ECMA)
  2. YUI extend() (YUILibrary)
  3. Prototype Classes and Inheritance (Prototype)
  4. Creating and Enhancing Dojo Classes (SitePen)
  5. MooTools Class (MooTools)
时间: 2024-11-08 15:20:45

[译]JavaScript需要类吗?的相关文章

[译]JavaScript中,{}+{}等于多少?

[译]JavaScript中,{}+{}等于多少? 原文:http://www.2ality.com/2012/01/object-plus-object.html 最近,Gary Bernhardt在一个简短的演讲视频“Wat”中指出了一个有趣的JavaScript怪癖:在把对象和数组混合相加时,会得到一些你意想不到的结果.本篇文章会依次讲解这些计算结果是如何得出的. 在JavaScript中,加法的规则其实很简单,只有两种情况:你只能把数字和数字相加,或者字符串和字符串相加,所有其他类型的值

[译]JavaScript规范-葵花宝典

原文:[译]JavaScript规范-葵花宝典 [译]JavaScript规范 译自:https://github.com/airbnb/javascript 类型 原始值: 相当于传值 string number boolean null undefined var foo = 1, bar = foo; bar = 9; console.log(foo, bar); // => 1, 9 复杂类型: 相当于传引用 object array function var foo = [1, 2],

JavaScript创建类的方式

一些写类工具函数或框架的写类方式本质上都是 构造函数+原型.只有理解这一点才能真正明白如何用JavaScript写出面向对象的代码,或者说组织代码的方式使用面向对象方式.当然用JS也可写出函数式的代码,它是多泛型的. 为了讨论的单一性,暂不考虑类的继承,(私有,受保护)属性或方法.EMCAScript中实际没有类(class)的概念,但可以把它理解为更广义的概念. 1.构造函数方式 /** * Person类:定义一个人,有个属性name,和一个getName方法 * @param {Strin

Javascript定义类(class)的三种方法

注:本文转自阮一峰,觉得此篇文章对我对大家有帮助,因此转过来. 将近20年前,Javascript诞生的时候,只是一种简单的网页脚本语言.如果你忘了填写用户名,它就跳出一个警告. 如今,它变得几乎无所不能,从前端到后端,有着各种匪夷所思的用途.程序员用它完成越来越庞大的项目.Javascript代码的复杂度也直线上升.单个网页包含10000行Javascript代码,早就司空见惯.2010年,一个工程师透露,Gmail的代码长度是443000行! 编写和维护如此复杂的代码,必须使用模块化策略.目

Atitit.javascript 实现类的方式原理大总结

Atitit.javascript 实现类的方式原理大总结 1. 实现类的式::构造方法方式:原型方式:构造方法+原型的混合方式 1 2. 原型方式(function mode)经典式..实现属性推荐 1 3. this的注意事项 2 4. 原型方式 prototype,实现方法推荐 3 5. 混合方式(属性classic mode,方法propoty式),推荐 3 6. 私有方法 4 7. 静态的属性and方法... 5 8. 闭包式 5 9. mootools框架,感觉很不错,它对Javas

【Javascript】类

定义一个类来表示2D平面几何中的点.这个类实例化的对象拥有一个名为r()的方法,用来计算该点到原点的距离 function Point(x,y){ this.x = x; this.y = y; } var p = new Point(1,1); Point.prototype.r = function(){ return Math.sqrt(this.x*this.x + this.y*this.y); } p.r(); [Javascript]类,布布扣,bubuko.com

JavaScript学习总结(十四)——JavaScript编写类的扩展方法

在?J?a?v?a?S?c?r?i?p?t?中?可以使?用?类的p?r?o?t?o?t?y?p?e属性来?扩?展?类的属?性?和?方?法,在实际开发当中,当JavaScript内置的那些类所提供的动态方法和动态属性不满足我们实际开发时,我们就可以通过"prototype"属性给自定义类添加方法和属性或者扩展原有的类中的方法和属性. 一.扩展JavaScript内置类,添加动态方法 语法格式: 类名.prototype.方法名 = function([param1],[param2],.

JavaScript定义类的方式与其它OO语言有些差异

JavaScript面向对象的程序编写与其它OO语言有一些出入,所以使用JavaScript的面向对象特性的时候,需要注意一些规范性的问题.下面就简单地谈一下,JavaScript如何定义一个类,在定义类的过程中需要如何规范你的代码.定州市科技工业局 使用javascript来定义类的规范如下: 指定类名与构造函数,类名(构造函数名)首字母大写: function YourClass(){ } 使用"this.成员变量"在其构造函数内定义(伪)私有成员,最好约定(伪)私有成员都以&qu

方格拼图游戏2(javascript以类的形式实现)+增加批量移动

今天又在原来的基础上,增加了新的功能:当空白方格A 与 鼠标点击的方格 B在同一行,或者同一列,而且当他们不是紧挨着的情况,自动将B到A间的方格们,顺次移动填补空白方格. var game ={ wid_num:3, cotainerid:"game_cotainer", init:function(_num){ console.log('init'); game.wid_num = _num || 3; console.log( game.wid_num ); var max_num