[译]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)

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

  1. 详解javascript的类

    前言 生活有度,人生添寿. 原文地址:详解javascript的类 博主博客地址:Damonare的个人博客 Javascript从当初的一个"弹窗语言",一步步发展成为现在前后端 ...

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

    将近20年前,Javascript诞生的时候,只是一种简单的网页脚本语言.如果你忘了填写用户名,它就跳出一个警告. 如今,它变得几乎无所不能,从前端到后端,有着各种匪夷所思的用途.程序员用它完成越来越 ...

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

    Atitit.javascript 实现类的方式原理大总结 1. 实现类的式::构造方法方式:原型方式:构造方法+原型的混合方式 1 2. 原型方式(function mode)经典式..实现属性推荐 ...

  4. [转]Javascript定义类的三种方法

    作者: 阮一峰 原文地址:http://www.ruanyifeng.com/blog/2012/07/three_ways_to_define_a_javascript_class.html 将近2 ...

  5. javascript 定义类(转载)

    Javascript本身并不支持面向对象,它没有访问控制符,它没有定义类的关键字class,它没有支持继承的extend或冒号,它也没有用来支持虚函数的virtual,不过,Javascript是一门 ...

  6. javascript定义类和类的实现

    首先说说类,在一个类里我们会有以下的几个特征: 1. 公有方法 2. 私有方法 3. 属性 4. 私有变量 5. 析构函数 我们直接看一个例子: /***定义类***/ var Class = fun ...

  7. javascript创建类的6种方式

    javascript创建类的7种方式 一 使用字面量创建 1.1 示例 var obj={}; 1.2 使用场景 比较适用于临时构建一个对象,且不关注该对象的类型,只用于临时封装一次数据,且不适合代码 ...

  8. JavaScript一个类继承中实现

    JavaScript类是默认原型对象继承: var Person = function() { this.name = "people"; this.hello = functio ...

  9. Javascript创建类和对象

    现总结一下Javascript创建类和对象的几种方法: 1.原始的创建方法: <script type="text/javascript"> var person = ...

随机推荐

  1. 常见到的runtime exception

    ClassCastException    类转换异常 IllegalArgumentException   非法参数异常 IndexOutOfBoundsException   数组越界异常 Nul ...

  2. 转!mysql备份与还原数据库

    备份数据库:1) mysqldump -uroot -p db_name > 20181018_preprod_bak.sql2) 输入数据库密码 还原数据库:1. 系统命令行:mysqladm ...

  3. npm install命令对package-lock.json文件自动做了一些额外的更新

    今天我使用 npm 命令给项目安装file-saver,通过git却发现package-lock.json中除了file-saver组件之外的其他组件的记录也被改了 npm为何会自动做这些更改呢,又如 ...

  4. vs中nodejs代码 resharper 提示 ECMAScript2015 Feature. your Current language level is ECMAScript5的解决办法

    问题如图 错误信息:ECMAScript 2015 Feature. your Current language level is: ECMAScript5 解决方法, 打开 Resharper -& ...

  5. SIP中的 session, dialog 及 transaction 的解释

    http://stackoverflow.com/questions/35133331/difference-between-session-dialog-and-transaction-in-sip ...

  6. 解决shell脚本参数传递含有空格的问题

    有这样一个py文件,需要传一个字典作为参数: import json import sys def parse_params(data): json_data = json.loads(data[1] ...

  7. css 自定义滚动条

    我遇到的场景: 对于iframe窗口,自带滚动条是整个窗口的大小.有时需要顶部或底部固定,则滚动条不应该触碰到顶部或底部. 那么首先打开iframe时应该去掉滚动条 scrolling="n ...

  8. python3 用requests 保存网页以及BeautifulSoup保存图片,并且在本地可以正常显示文章的内容和图片

    用requests 模块做了个简单的爬虫小程序,将博客的一篇文章以及图片保存到本地,文章格式存为'.html'.当文章保存到本地后,图片的连接可能是目标站点的绝对或者相对路径,所以要是想在本地也显示图 ...

  9. [C语言]删除用户自定义后缀名的所有文件

    环境:win7 IDE:DEV-C++ 编译器:GCC 编译结果:Success 运行结果:Success 使用说明: 1.输入需要查询的目录,比如e: 2.输入需要删除的后缀名:比如:txt 注意: ...

  10. Mac OS X 10.10 Yosemite下配置 apache+php

    自从系统从OS X Mavericks 10.9升级到OS X Yosemite 10.10 后之前配置apache和php均不能正常使用了, 重新设置配置如下: 首先,查看当前系统的apache版本 ...