对象 vs 类 vs 函数

Posted

技术标签:

【中文标题】对象 vs 类 vs 函数【英文标题】:Object vs Class vs Function 【发布时间】:2013-07-05 17:10:03 【问题描述】:

我想知道 - 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'

当然,类有方法和属性并且可以被实例化——但是,我可以对任何旧函数做同样的事情——或者不?

【问题讨论】:

类已在 ECMA 6 中引入:developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/… 类现在在许多 post node.js Javascript 库等中很常见。说 Javascript 中没有类 不再正确。现在有类,浏览器实现还没有很好地支持这些类(还没有),但是在 NPM 和 Node.js 时代,类在很大程度上是语言向前发展的核心概念(这只是我当时欣赏的仅供参考在这里写第一条评论是正确的)。 【参考方案1】:

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 并返回该对象。称为new functionA() 的函数应作为构造函数工作并准备一个新创建的对象(this)。在你的情况下 - 构造函数对对象不做任何事情,只是提醒bar

【讨论】:

你应该澄清最后一句话。【参考方案2】:

javascript 中没有类。但是,有一些方法可以让函数表现得像其他语言中的类。

这里给出了很好的解释3 way to define a class in js

另外,为OOP in Javascript找到了一个很好的参考

【讨论】:

从 ECMAScript 2015 开始,Javascript 中有 @Liam 是语法糖。它仍然是一个底层函数。 @NikitaShahov -- 这只是类在 javascript 中的实现方式,并不意味着没有类。甚至私人会员现在也即将成为现实。 (这是第 3 阶段的提案:github.com/tc39/proposal-private-methods)【参考方案3】:

您现在必须知道,JavaScript 中没有类。相反,通过在函数调用前加上 new 关键字,可以使 JavaScript 中的函数表现得像构造函数。这被称为constructor pattern。

在 JavaScript 中,除了原始数据类型(布尔、数字和字符串)和 undefined 之外,一切都是对象。另一方面,null 实际上是一个对象引用,即使您起初可能不这么认为。这就是typeof null 返回"object" 的原因。

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

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

阅读以下主题以了解有关 JavaScript 中原型继承的更多信息:Benefits of prototypal inheritance over classical?

【讨论】:

@bits 恐怕你错了。您会看到 JavaScript 中有两种类型的布尔值,数字和字符串 - 基元和包装对象。 JavaScript 中的文字值被视为原语。例如文字true3.14"Hello World!" 都是原始数据类型。当您在它们上使用typeof 时,它们分别返回"boolean""number""string"。然而,JavaScript 允许您将它们用作对象,并在需要时将它们强制转换为对象。因此,您可以执行"abc".slice(-1) 之类的操作。这就是我们在 JavaScript 中使用 valueOf 运算符的原因。 这个答案现在已经过时了 是的@DhavalJardosh null 是原始值之一。它不是一个对象。 typeof null === "object" 简直就是 JS 近二十年来的一个 bug。 null 是原始值。【参考方案4】:

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

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

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

我希望在 ECMAScript 6 中,我们可以清楚地区分这些结构,类似于我们在 C#、Java 等其他语言中的结构。

【讨论】:

【参考方案5】:

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();

你可以期待这个对象的任何东西,就像你对其他语言的对象一样。只是实现它的努力,有点不同。您还应该查看inheritance in 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'.

【讨论】:

基于原型的编程不是“人们发现的一种模仿面向对象实践的方式”。它一种面向对象编程的方式,早在 JavaScript 之前就发明了,并且是基于类的编程的替代方案。【参考方案6】:

2015 年更新

JavaScript 中有一些类,它们只是在旧版浏览器上没有使用:

https://developer.mozilla.org/en-US/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.');
  

【讨论】:

我认为重要的是不要让新的类构造函数是最新 JavaScript 的一部分,因此仅受支持,它们只是一种新语法,它们实际上是函数,它们只是被设计为语法糖为了使代码更有条理,它们与函数构造函数没有任何不同。 这些仍然不是经典继承意义上的“类”,而只是用于连接链接到其他对象 (OLOO) 的对象的语法糖,以近似经典继承的行为。尽管关键字给了您这种错觉,但 JavaScript 中没有类。【参考方案7】:

您还可以在 ES6 中获得如下所示的类:

//class
class Cat 
    //constructor
    constructor() 
        this.name = 'Snowball';
    

    //method
    meow() 
        console.log('Hello, nyah! My name is ' + this.name + ' nyah!~');
    
;

【讨论】:

那个方法需要一个“函数”,不是吗? @sorak 不再,见developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…

以上是关于对象 vs 类 vs 函数的主要内容,如果未能解决你的问题,请参考以下文章

vs2010中写c#,写了很多类,想在类里面添加main()做函数入口测试,但不能单独运行这个类

C++虚函数总结

面向对象常用方法

C++ 对象 & 类

如何开发插件实现vs快速生成构造函数

模块函数 vs 静态方法 vs 类方法 vs 无装饰器:哪个成语更 Pythonic?