对象,类,功能


78

我想知道-JavaScript对象,类和函数之间有什么区别?我认为类和函数是对象的类型对吗?

什么使类与函数有区别?还是它们真的是同一回事,只是针对它们的术语会根据其用法而变化?

function func() { alert('foo'); } // a function
func(); // call the function - alerts 'foo'
var func2 = function () { alert('hello'); } // acts the same way as 'func' surely?
func2(); // alerts 'hello'

var Class = function() { alert('bar'); }; // a class
var c = new Class(); // an istance of a class - alerts 'bar'

当然,类具有方法和属性并且可以实例化-但是,我可以对任何旧函数执行相同操作-还是不可以?


11

5
现在,类在许多node.js后的Javascript库等中很常见。不再正确地说Javascript中没有类。现在有一些类,这些类还没有被浏览器实现很好地支持(但是),但是在NPM和Node.js时代,类是语言向前发展的核心概念(这只是当时的FYI,我很欣赏在这里写第一个评论是正确的)。
利亚姆

Answers:


69

正如您现在必须已经意识到的那样,JavaScript中没有类。取而代之的是,可以通过在函数调用之前添加new关键字来使JavaScript中的函数像构造函数那样工作。这称为构造函数模式

在JavaScript中,除了原始数据类型(布尔,数字和字符串)和之外,所有都是对象undefined。另一方面null,实际上您实际上是一个对象引用,即使您一开始可能会不同意。这就是typeof null回报的原因"object"

JavaScript中的函数类似于Lua中的函数(即,它们是可调用的对象)。因此,可以使用功能代替对象。同样,数组也是JavaScript中的对象。另一方面,可以将对象视为关联数组。

然而,最重要的一点是JavaScript中没有类,因为JavaScript是一种原型的面向对象语言。这意味着JavaScript中的对象直接从其他对象继承。因此,我们不需要类。我们需要的是一种创建和扩展对象的方法。

阅读以下主题,以了解有关JavaScript中原型继承的更多信息:原型继承相对于经典继承的好处?


1
非常感谢您的回答!我已经阅读了有关该主题的内容,并且我认为现在知道了。因此,您建议在构造函数模式上使用原型模式吗?
肖恩·伯恩

1
@SeanBone:我建议在学习构造函数模式之前先学习原型模式,因为这样可以更容易地理解原型继承。但是,构造函数模式比JavaScript中的原型模式要快。因此,如果您想编写对性能至关重要的代码,则使用构造函数模式更为合理。尽管如此,原型模式仍然相当快,请放心,您几乎不需要额外的性能提升。JavaScript解释器在优化代码方面做得很好。因此,大多数时候您应该坚持使用原型模式。
Aadit M Shah

1
@bits恐怕你错了。您会看到JavaScript中有两种类型的布尔值,数字和字符串-原语和包装的对象。JavaScript中的文字值被视为原语。例如,文字true3.14"Hello World!"都是原始数据类型。当您使用typeof上他们,他们返回"boolean""number""string"分别。但是,JavaScript允许您将它们用作对象,并在需要时将其强制为对象。因此,您可以做类似的事情"abc".slice(-1)。这就是我们valueOf在JavaScript中使用运算符的原因。
Aadit M Shah

9
这个答案现在已经过时了
利亚姆

1
是的@DhavalJardosh
Liam

41

更新2015

JavaScript中有一些类,它们仅在较旧的浏览器中不使用:

兼容性截图

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

它具有构造函数,扩展名等。

class Cat { 
  constructor(name) {
    this.name = name;
  }
  
  speak() {
    console.log(this.name + ' makes a noise.');
  }
}

class Lion extends Cat {
  speak() {
    super.speak();
    console.log(this.name + ' roars.');
  }
}

6
我认为重要的是不要让新的类构造函数成为最新JavaScript的一部分,因此仅受其支持,它们只是一种新语法,它们实际上是功能,只是被设计为语法糖,以使代码更加有条理函数的构造函数没有什么不同。
Binvention '16

2
从经典继承的意义上讲,这些仍然不是“类”,而仅仅是用于以近似经典继承行为的方式连接与其他对象(OLOO)链接的对象的语法糖。尽管关键字给了您这种错觉,但JavaScript中没有类。
Andy Fusniak

18

JS中的一个类:

function Animal(){  

    // Private property
    var alive=true;

    // Private method
    function fight(){ //... }   

    // Public method which can access private variables
    this.isAlive = function() { return alive; } 

    // Public property
    this.name = "Joe";
}

// Public method
Animal.prototype.play = function() { alert("Bow wow!"); }

// .. and so on

现在,当您创建对象时

var obj = new Animal();

您可以像使用其他语言的对象一样期待此对象的任何内容。只是实现它的努力有些不同。您还应该查看JS中的继承


再次得到您的问题,我将其改写为:

Class  : A representation of a set with common properties.
object : One from the set with the same properties.


var Class = function() {alert('bar');}; // A set of function which alert 'bar'
var object = new Class();               // One of the functions who alert's 'bar'.

3
基于原型的编程并不是“人们发现模仿面向对象实践的一种方式”。它面向对象编程的一种方法,它在JavaScript之前发明的,并且是基于类的编程的替代方法。
更好的Oliver

9

JavaScript没有类,而函数实际上是JavaScript中的对象(一等公民)。函数对象唯一的区别在于它们是可调用的

function func() { alert('foo'); } // a function -正确

func(); // call the function - alerts 'foo' -正确

var func2 = function () { alert('foo'); } // same as 'func' surely?-不,func2是一个不同的对象,在调用时显然执行相同的操作。

var Class = function() { alert('bar'); };-这是一个没有名称存储在变量中的函数Class

var c = new Class();-调用存储在Class提供新的空对象作为this并返回该对象的函数。被称为as的函数new functionA()可以用作构造函数并准备一个新创建的对象(this)。在您的情况下,构造函数对对象不执行任何操作,仅发出警报bar


3
您应该澄清最后一句话。
adrianp

3

javascript中没有类。但是,有一些方法可以使函数像其他语言中的类一样工作。

这里给出了一个很好的解释在js中定义类的3种方法

另外,在Javascript中OOP找到了很好的参考


1
从ECMAScript 2015开始,Java语言提供了一些
Liam

@Liam是语法糖。它仍然是后台功能。
Nikita Shahov,

2
@NikitaShahov-这就是在javascript中实现类的方式,并不意味着就没有类。甚至私人成员也将成为一件事情。(这是第3阶段的建议:github.com/tc39/proposal-private-methods
浮士德

3

Object是JavaScript中的基本类型,即所有用户定义的数据类型都以一种或另一种方式从Object继承。因此,如果您定义函数或类[注意,到目前为止JS不支持类构造,而是在ECMAScript版本6中提出的],它将隐式继承自Object类型。

类实际上是用于将逻辑函数和属性封装到一个类型/实体中的,您可以使用构造函数语法对其进行“更新”。因此,如果定义“客户”类,则可以实例化多次,并且每个实例/对象可以具有不同的值。如果您使用原型定义类级别值,它们甚至可以共享值。

由于JS目前不支持类构造,因此函数实际上可以充当单个方法以及其他函数或类型的容器。

我希望通过ECMAScript 6,我们可以在这些结构之间实现清晰的分离,类似于我们在其他语言(如C#,Java等)中所具有的结构。


By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.