每个对象都是一个函数,每个函数都是一个对象 - 哪一个是正确的?

51

我在阅读这个链接 JavaScript_syntax

似乎循环了——每个函数都是一个对象,而每个对象本身也是一个函数。哪个是原子的?有人能用更好的方式解释一下吗?


35
当你完全理解它时,你将达到涅槃境界。 - FrustratedWithFormsDesigner
javascript:alert(Object) 告诉我们: function Object() { [native code] } 这表明 Object 是一个函数! - Ekim
至少在使用以下代码时:javascript:alert(window.navigator.userAgent) Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.2.3) Gecko/20100423 Ubuntu/10.04 (lucid) Firefox/3.6.3 - Ekim
1
请查看此答案:https://dev59.com/1G025IYBdhLWcg3whGWx - Rohit
13个回答

65
  1. JavaScript中除了原始类型(undefined、null、数字、字符串、布尔)之外的任何内容都是对象(或实例)。这意味着function继承自object

  2. 对象实例可以包含更多的实例,其中可以包含函数。这就是我们所说的“方法”(因为它有一个自动的this变量)。

  3. 由于不能“调用”每个对象实例,因此并非每个对象都是函数。


9
函数是 Function 的实例(很可能是继承自 Object),正如 OP 引用的文章所述:http://en.wikipedia.org/wiki/JavaScript_syntax#Function - FrustratedWithFormsDesigner
7
尝试这个:var obj={}; obj(); 这是“尝试调用对象”(即像函数一样使用它)。 不起作用。 因此,任意对象不是一个函数。 - Aaron Digulla
变量 num = 5; 在这行代码中,num 是一个对象,因为它有属性和原型定义。这是正确的吗?还是我漏掉了什么?同样的情况也适用于字符串和布尔值吗?虽然 undefined 和 null 似乎本身就是不同的类型? - Sid
1
关于问题#1,为什么typeof null是一个object - allenhwkim
@allenhwkim 这是 typeof 中的一个 bug。null 就像 5 一样是原始类型。请参见 https://dev59.com/f3RA5IYBdhLWcg3w2x2W,特别是这个答案:https://dev59.com/f3RA5IYBdhLWcg3w2x2W#7968470。 - Aaron Digulla

20

我认为这个概念经常被误解。

一个可视化 JavaScript 类型关系的实用工具:http://jstype.herokuapp.com/#/home

Javascript 数据类型

  1. 基本类型 - 数字、字符串、布尔值、null 和 undefined。
  2. 所有非基本类型均为对象

var foo = { }; 
var foo = [1, 2, 3]; 
var foo = function abc() { return "hello world"; }; 
var foo = new Number(30); 
var foo = new String("Hello World"); 
var foo = new Boolean(true); 
var foo = new RegExp(/[foo]+/);

// All 'foo` are object. 

  1. 所有原始类型都有相应的构造函数,如Array、Number、String、Boolean、RegExp等。由于所有函数都是对象,它们也是对象。因此,我们可以称它们为构造函数对象。

  2. 大多数非原始类型都有 prototype 属性,其中包含所有继承的内容。Math 没有原型。

  3. 所有对象都从 Object.prototype 继承,后者从 null 继承。
    object <- Object.prototype <- null

  4. 所有本地函数都继承自 Function.prototype,它又从 Object.prototype 继承。
    function <- Function.prototype <- Object.prototype <- null

  5. 数组继承自 Array.prototype,它又从 Object.prototype 继承。
    array <- Array.prototype <- Object.prototype <- null

必读 MDN:继承和原型链
容易混淆的请参考 Stackoverflow:JavaScript 中的原型
Stack Overflow:函数原型解释


1
var foo = function abc() { return "hello world"; }; typeof foo is function here and not object - Rahul Yadav
@Rahul 是的,但是 instanceof Object 返回 true。与预期相反,typeof 运算符并不总是给出“根类型”——它有一个特殊情况,即如果 Function.prototype 在原型链中,则返回 function,而不是根类型 object。基本上,所有函数仍然继承自 Object.prototype。(可以通过 (function(){}) instanceof Object(function(){}).__proto__.__proto__ == Object.prototype 来确认这一点,两者都返回 true。) - Venryx
null 继承自什么东西吗? - carloswm85

8

每个函数都是一个对象。对象可以包含函数(方法),但是一个对象不一定是一个函数。


8

另外,Function 总是一个 object 的属性。

这意味着 JavaScript 中的所有函数都始终绑定到一个对象。如果您没有指定要绑定函数的对象,则它将绑定到 window 对象(也称为全局函数)。

..fredrik


这个真的很棒。 - Abhishek

3

在JavaScript中,一切都可以被视为对象,包括原始类型和函数类型;JavaScript解释器会自动将您的原始类型和函数提升为它们的对象包装类型,以便与它们交互。

此外,还有一个Function对象,以及用于其他JavaScript原始类型的等效包装器,这意味着您甚至可以在函数实例上调用方法,例如:

myFunction(someArg).call(this)

说到这一点,并不是每个对象都是一个函数。

但是...每个 Object 都是 function Object() {[native code]} - Ekim
所以每个 Object 都是一个函数! - Ekim
除非重新定义ObjectObject=null,否则不要返回翻译文本。 - Ekim
但在这种情况下,null是一个原始值而不是对象 - 不是Object不是Function的有效示例。 - RickB
请区分语言层面上的“对象构造函数/定义”和实际的“对象”。看到每个答案和评论都说相反的话真是太痛苦了。function Object 是基本对象的定义方式,但在底层它仍然是一个带有属性(lengthname 等)的对象。 - Kamafeather

3

正如其他人所说,函数是可以像其他 JavaScript 对象一样通过引用传递的对象。并非所有的对象都是函数,只有那些声明为函数的才是。

您经常会看到像这样声明方法:

var myFunc = function(foo, bar) {
    ...
};

这旨在强调该方法是一个函数对象,因此它是定义它的对象的属性,就像您可能使用var定义的任何其他变量一样。

这是Javascript最重要的功能——闭包的基础。


但是每个Javascript对象也是Object的一个实例,而Object本身是一个函数(可以用new关键字初始化,如new Object()),而该函数又是Function的一个实例,而Function又是Object的一个实例? - doubleOrt

1

引用自与对象一起工作-MDN文档
使用对象初始化器段最后一句话:

“在JavaScript 1.1及更早版本中,您无法使用对象初始化器。您只能使用它们的构造函数或使用某些其他对象提供的函数来创建对象。请参见使用构造函数。”

这意味着所有对象都是函数!具体来说,是在函数实例化或实例化时进行评估。

从字面上讲,那个年代的所有对象都是使用类似以下结构的语法创建的:

 "newobj = new constructFunctor(arg1,arg2){this.prop1=arg1 /* etc */}(val1,val2)"

在构造对象"newobj"的字符串中,存在函数名为"constructFunctor"的单词。这个语句被有意引用以强调必须使用eval()来执行它。在执行之前,"newobj"被“等同于”一个函数,因为该语句必须具有一个函数,并且由于"constructFunctor"的字面存在来定义newobj的值。引用和不引用都是非常有意义的,以阐明这种抽象。然而,由于JavaScript确实有一个eval函数,因此这种抽象实际上已经被纳入了JavaScript语言。

尽管一些语法快捷方式已经添加为“对象初始化器”,例如使用缩写符号"no={}",但这种抽象仍然是JavaScript的基础。以上引用段落在当前文档中仍然存在,这一点非常重要,正如上述原因所述。

此外,JavaScript 也展示了函数式编程的基本范例。这使用递归函数理论和 Lambda 演算的抽象将所有内容定义为函数!例如,0()、1()、2() 等是常量九进制函数,更为人所知的是 0、1、2、3 等。
JavaScript 完全符合函数式编程风格的方法,而不是常见的面向对象编程风格(意在讽刺)。

1
仅作为对Aaron Digulla答案的补充。 在javascript中,并不是每个对象都是函数。但Object、Array、String和许多其他内置对象是函数,可以使用new运算符创建对象。我认为这是最让人困惑的地方。

那么,每个对象不都是 Object 的实例吗?你能详细说明一下吗?有没有一种创建对象的方法不涉及 Object - doubleOrt

1
每个函数都是一个对象。
我不是 JavaScript 专家,但我无法看出每个对象都是一个函数。(我可以看出每个对象可能是一个函数,但那是不同的)

3
Object 是一个函数,代码实现是 [native code]。所有的东西都是对象... 因此,所有的东西都是函数... 嗯... - Ekim

1

对象是赋予类的抽象数据,该类被分配给一个对象。对象可以有属性,属性可以包含值和函数。 或者简单地说,为了使其易于理解,您可以说任何不是原始数据类型(数字、字符串、布尔值、null和undefined)的东西都可以归类为对象。


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