JavaScript有类吗?

86
上周我和一个朋友发生了争论。他说JavaScript中没有类这个概念。
我说有,因为你可以使用var object = new Object()这样的语法。
他说:“因为没有使用class这个关键词,所以它不是一个类。”
谁是对的?
注意:此问题是在 ECMAScript 第六版(2015年)引入 class 语法 之前提出的。即便如此,正如上面所提到的,仅仅有此语法的存在并不能必然解决问题。

在上面的例子中,它谈论了类Rectangle,所以为了定义一个类,我们不再需要使用函数关键字,即(function Rectangle(dimensions) { }?现在有一个class关键字用于类? - Roxy'Pro
我发现了这个 Reddit 帖子,它提供了很多人对这个话题的看法。大多数人似乎认为 ES6 类是真正的类,但当然也有一些不同的意见。任何想深入探讨这个问题并形成自己观点的人都可以去看看:https://www.reddit.com/r/javascript/comments/8q6267/why_are_js_classes_not_real_classes/ - Scotty Jamison
15个回答

122

从技术上讲,"JavaScript没有类"的说法是正确的。

虽然JavaScript是面向对象语言,但它不是基于的语言——它是基于原型的语言。这两种方法之间存在差异,但由于可以像使用基于类的语言一样使用JavaScript,因此许多人(包括我自己)通常将构造函数简单地称为"类"。


4
你可以使用原型模式模拟类并使用类模拟原型,例如查看原型设计模式。 - Gabriel Ščerbák
我想我赚到了五英镑!干得好,史蒂夫。 - Glycerine
2
@SteveHarrison,ECMAScript 2015 中引入的 JavaScript 类主要是对 JavaScript 现有基于原型的继承语法糖的补充。因此这意味着 JavaScript 正在成为基于类的语言吗? - Roxy'Pro
是的,作为Java开发人员,我经常向人们指出这一点。Javascript有“对象”但没有类。人们所谓的“类”实际上是一个对象。 - Orubel
3
尽管ES6类大多是语法糖,但任何想要将它们视为不真实的人都必须小心,不要使用那些也排除其他动态语言中的类的参数。Javascript类已经变得和Python类一样真实。 - Scotty Jamison

28

Javascript是一种面向对象的编程语言,然而在2015年,通过ECMA script 6引入了类(class),现在可以像其他基于类的语言(如Java)一样使用它们。当然,正如用户codemagician在他/她的评论中指出的那样,JS中的类和Java或其他“基于类”的编程语言的类工作方式存在一些深刻的差异。

尽管如此,在js编程中现在可以使用例如以下代码:

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


class Dog extends Animal {
  speak() {
    console.log(this.name + ' barks.');
  }
}

来源:https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Classes

这与经典基于类的语言有些共同之处。问题在于,这项新技术的浏览器支持目前还只是刚刚开始。因此,在生产产品上使用它仍然不太好。但我毫不怀疑,这个问题很快就会得到解决。

因此,问题在于由于实现了这些新特性,js 是否已经成为了一个基于类的编程语言,还是仍然保持着面向对象的原型编程语言。


嗨。感谢您的评论。我不想引起争议,但问题是“JavaScript有类吗?”我说:“ECMA script 6在2015年引入了js中的类”在我看来,这给出了一个更新的答案...是吗? 同时,我的回答也试图与其他开发人员交流他们对这种新的EC6情况的看法。如果我错了,那我很抱歉。 - willy wonka
2
我可以谦虚地问一下为什么会有负评,这样我就可以从自己的错误中学习吗?提前感谢。 - willy wonka
我没有点踩。我猜是因为标记的缘故。通常它们是罪魁祸首。等一两天。其他领域专家会看到你的帖子并相应地投票。不要太担心这些突然的负评。 - Bhargav Rao
2
@Bhargav Rao 哦,好的,无论如何我并没有说你是那个给我投反对票的人:我并不是在指责任何人,我只是希望得到一个解释,以便改善我的行为,让自己和其他人在这个很棒的社区中受益:我会慢慢来的,毕竟我还是新手,;-) - willy wonka
4
你的回答有误导性。说“现在可以像Java这样使用它们”是不正确的。Java是一种面向对象的类语言。类的实例在创建每个实例时会将属性的副本制作出来。“JS中的类”只是将对象连接到其他对象(OLOO)的语法糖,而JS的基本模型就是OLOO。OLOO模型始终使用原型链来提供“继承”(实际上是_委托_),从未真正复制“实例”属性。“类”并非真正的静态内容,就像真正的面向对象语言一样。 - Andy Fusniak

8

请在此处收听Douglas Crockford的讲话:
http://developer.yahoo.com/yui/theater/video.php?v=crockonjs-2

他在演讲中直接回答了您的问题:

这种语言最具争议的特点是它进行继承的方式,这与几乎所有其他现代语言都有根本的不同。大多数语言使用类 - 我称之为“经典语言” - 但JavaScript不是这样。JavaScript是无类的。它使用原型。对于那些受过经典培训的人来说,当他们看到这种语言时,他们会认为这很不足。你没有类,你怎么能完成任何事情?你怎么能确信你的程序结构会起作用?他们永远无法超越这一点。但事实证明...


1
视频托管在YouTube上https://www.youtube.com/watch?v=RO1Wnu-xKoY - Wulf Solter

7
在JavaScript中,几乎所有东西都是一个对象(对象可以从其他对象继承)。它没有传统意义上的。尽管可以通过函数原型实现大多数传统类定义/实例化的功能。

8
"在Javascript中,一切都是对象":不完全正确。还有原始值,比如undefinednull等。 - Marcel Korpel
void?JavaScript 中存在 void 吗?我是 AS3 的开发者,从未在 JS 中看到过 void。 - Glycerine
@Glycerine 在JavaScript中最接近AS3的void的东西应该是undefined - Yay295

5

来自 You-Dont-Know-JS 书中 https://github.com/getify/You-Dont-Know-JS 的内容

第四章:混合(上)“类”对象

...

JS 已经有了一些类似语法元素(如 new 和 instanceof)相当长的时间,最近在 ES6 中新增了一些关键字,如 class。

但这是否意味着 JavaScript 实际上拥有类?简单明了地说:不是

我不会复制并粘贴其他部分,但鼓励阅读第三章第四章并运行示例。

https://github.com/getify/You-Dont-Know-JS/blob/1st-ed/this%20%26%20object%20prototypes/ch3.md

https://github.com/getify/You-Dont-Know-JS/blob/1st-ed/this%20%26%20object%20prototypes/ch4.md



4

当人们说“语言X有类”时,通常指支持面向对象编程。

是的,Javascript是一种面向对象的语言。


1
JS是一种函数式语言。 - ndesign11
6
拥有一级函数并不等同于JavaScript是一种函数式编程语言。 - JLRishe

2
简单来说,是的。你只需要使用Babel.js转译器,因为除了Chrome浏览器外,所有浏览器都不支持它。JavaScript类是一种函数类型。使用class关键字声明类。我们使用函数表达式语法初始化函数,使用类表达式语法初始化类。
以下是使用函数定义JavaScript类的示例:

class Rectangle {
  constructor(height, width) {
    this.height = height;
    this.width = width;
  }
  // Getter
  get area() {
    return this.calcArea();
  }
  // Method
  calcArea() {
    return this.height * this.width;
  }
}

const square = new Rectangle(10, 10);

console.log(square.area); // 100


2
当我想到类时,我想到类型和类允许我定义新类型的事实。在js中,你不能创建新类型。你可以使用原型来做各种花式面向对象的操作,但是一切仍然是对象的事实真正地突出了js的无类特性。我认为,在谈论js时使用“class”术语会比丑陋的new运算符更加混淆js作为原型语言与js作为经典语言之间的区别。简而言之,仅仅因为js是面向对象的,并不意味着需要存在类。

1
补充其他答案,JavaScript没有类,尽管我开始看到一些描述它类似于类的语句,但我认为这只会使问题更加混乱。
JavaScript有原型而不是类,但它们实现了相同的功能,原型是定义对象的对象,因此产生了混淆。
原型是Java中类管理的私有内部状态的表示。与Java将该内部状态放在类中并提供用于操作行为的接口不同,JavaScript直接公开数据结构以供JavaScript程序直接操作。
这是我找到的关于此主题的最佳描述,原型不是类

0

是的。 是的,JavaScript有类和对象。 以下是使用JavaScript/NodeJS类和对象制作区块链的示例:

// coded by Alfrick Opidi in Smashing Magazine blog
// https://www.smashingmagazine.com/2020/02/cryptocurrency-blockchain-node-js/

const SHA256 = require('crypto-js/sha256');
const fs = require('fs')

class CryptoBlock{
    constructor(index, timestamp, data, precedingHash=" "){
     this.index = index;
     this.timestamp = timestamp;
     this.data = data;
     this.precedingHash = precedingHash;
     this.hash = this.computeHash();     
    }
    computeHash(){
        return SHA256(this.index + this.precedingHash + this.timestamp + JSON.stringify(this.data)).toString();
    }   
}

class CryptoBlockchain{
    constructor(){
        this.blockchain = [this.startGenesisBlock()];     
    }
    startGenesisBlock(){
        return new CryptoBlock(0, "01/01/2020", "Initial Block in the Chain, its also called genisis", "0");
    }
    obtainLatestBlock(){
        return this.blockchain[this.blockchain.length - 1];
    }
    addNewBlock(newBlock){
        newBlock.precedingHash = this.obtainLatestBlock().hash;
        newBlock.hash = newBlock.computeHash();        
        this.blockchain.push(newBlock);
    }
}

 let smashingCoin = new CryptoBlockchain();

smashingCoin.addNewBlock(new CryptoBlock(1, "01/06/2020", {sender: "Iris Ljesnjanin", recipient: "Cosima Mielke", quantity: 50}));
smashingCoin.addNewBlock(new CryptoBlock(2, "01/07/2020", {sender: "Vitaly Friedman", recipient: "Ricardo Gimenes", quantity: 100}) );
fs.writeFile('genisis.json', JSON.stringify(smashingCoin), function (err) {
    if (err) throw err;
    console.log('Saved!');
  }); 
console.log(JSON.stringify(smashingCoin, null, 4));

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