【问题标题】:Is `Object` a function in JavaScript?`Object` 是 JavaScript 中的函数吗?
【发布时间】:2019-07-18 13:44:31
【问题描述】:

考虑这个函数:

function Foo(){
    var a = "3";
};

根据__proto__ VS. prototype in JavaScript

Foo.__proto__ = Function.prototype
Function.prototype.__proto__ = Object.prototype

我理解那部分,但如果我在 Google Chrome 控制台中执行此操作:

Object.__proto__
output: ƒ () { /* native code */ }

Function.__proto__
output: ƒ () { /* native code */ }

Q1:他们为什么指向函数? FunctionObject 实际上是什么,它们之间有何不同,因为 Object 实际上是一个函数?:

typeof Object
"function"

Q2:如果在 JavaScript 中一切都是对象,那为什么Object 是一个函数呢?另外,函数是如何在 JavaScript 中实际实现的?函数内部声明的变量会发生什么? JavaScript 编译器是否将函数转换为对象?

对不起,如果我遗漏了一些明显的东西。我真的对 JavaScript 中函数和对象的实现方式感到困惑。

【问题讨论】:

  • 请注意“对象”(概念)和函数“对象”之间存在差异。在 JavaScript 中,所有函数都是对象,包括“对象”。另一方面,并​​非所有对象都是函数(例如var a = {}
  • 不过,您正在这样做:Object.__proto__ => 您从Object 获得属性__proto__,这是一个function,因此是一个object
  • 你完全可以做到,例如。 Foo.a = 5。但请注意,这与您在函数内部 声明的变量无关。函数的内容只是与函数关联的一段代码,它的范围不是你所指的“对象”部分。
  • 你在测试中搞砸了一些东西。将属性添加到函数是完全合法的并且正在努力。比如jQuery的$是一个函数,但是你可以调用它的一些方法,比如$.each()
  • 只是为了确定,请参阅another fiddle = )。

标签: javascript prototype


【解决方案1】:

Q1:他们为什么指向 Function?

A1:因为它们是函数。 FunctionObject 只是构造函数。

函数是Function object。对象是Object object

Q2:如果在 JavaScript 中一切都是对象,那为什么Object 是一个函数?

A2:因为Object 只是一个构造函数。

typeof Object
// 'function'
typeof new Object()
// 'object'

而函数是Function 的一个实例,所以这使得函数成为对象。

(function(){}) instanceof Function
// true

【讨论】:

  • "函数是函数的一个实例,所以它是一个函数对象。"为什么会产生一个函数对象?
  • 我想说的是,Function 构造了一个函数对象
  • 如果是函数,为什么叫对象?
  • 因为它是Function的对象Functionfunction 之间的区别是一个点。
【解决方案2】:

Object 是所有对象的构造函数。所以,typeof Object==="function"

这是一个用于可视化的 sn-p:

console.log(typeof Object)            //function (which is an object)
var object=new Object()               //An instance of Object 'class'
console.log(typeof object)            //object
console.log(object instanceof Object) //true, because object is created by Object()

Function构造函数所有函数(包括它自己...)

所以,虽然并非一切都是函数,但大多数大写原生标识符都指的是构造函数。

【讨论】:

    【解决方案3】:

    基本上

    Functions 有一些可以执行的代码。
    Object 是那些包含数据的。

    对于具有xy 的类Point

    class Point {
        constructor(x, y) {
            this.x = x;
            this.y = y;
        }
        isOrigin() { return x == 0 && y == 0; }
    }
    let p = new Point();
    

    回答 1

    在此,pobject,其中包含数据或其他功能。

    p.isOrigin 是函数。

    同样,Point 类本身就是一个function,当运行 时会产生p。这就是为什么像ObjectFunctions 这样的所有类都是functions,更准确地说是constructor functions

    答案 2

    如果 JavaScript 中的一切都是对象,那为什么 Object 是一个函数?

    与答案 1 相同。

    另外,一个函数是如何在 JavaScript 中实际实现的?

    不同的 JavaScript 引擎会有不同的实现。他们有需要遵循的规范。

    函数内声明的变量会发生什么变化?

    题外话。每个function 都在一个范围内运行,该范围包含该函数的所有数据。

    JavaScript 编译器是否将函数转换为对象?

    不知道你在问什么。

    【讨论】:

    • 如果已回答,请关闭此问题。问另一个问题。 this 关键字本身就是一个巨大的话题。 medium.com/quick-code/…
    【解决方案4】:

    Function 和 Object 都是构造函数,可分别用于创建函数和对象,这就是 typeof Function 返回 function 的原因。

    关于javascript中函数和对象的关系,请考虑以下几点:

    1. 所有非原始类型都是 JavaScript 中的对象。
    2. 所有对象都直接或间接继承自 Object.prototype(除非使用 setPrototypeOf 显式更改原型)。
    3. 所有原生函数都继承自 Function.prototype 继承自 Object.prototype,因此这意味着函数间接继承自 Object.prototype,因为函数在 JavaScript 中被视为对象。
    4. 函数被视为对象的原因是因为它们可以作为参数传递给其他函数并且可以从函数返回,即高阶函数(javascript 的一个强大功能)。
    5. 可以使用 () 运算符调用函数,因为 JavaScript 引擎知道它是使用 function 关键字声明的并且具有可执行代码。因此,无论何时调用它,JavaScript 引擎都会创建一个新的执行上下文并设置this 绑定,然后执行该函数。当您尝试调用对象时,这些都不会发生,而是会引发错误,即“不是函数”。

      所以我们可以说不是每个对象都是函数,因为它们可能没有使用 function 关键字声明并且没有可执行代码。

    6. 由于函数在 JavaScript 中被视为一个对象,我们可以向它添加属性,从中创建新对象。
    7. 不能使用() 调用非函数类型对象,因为它没有可执行代码并且未使用function 关键字声明。相反,它使用new Object() 或对象表示法声明并包含方法和属性。

    我希望它可以解决这两个问题。

    【讨论】:

    • 没有。不是所有的对象都继承自Object.prototype,也不是所有的函数都继承自Function.prototype。函数是可调用的,因为这是它们的内在特性(使这些对象起作用的原因),而不是因为它们继承自 Function.prototype。同样,对象可以具有属性,因为这是定义对象的原因,而不是因为它们继承自 Object.prototype。继承链(其存在是作为对象的另一个特征)仅影响可访问的继承属性/方法,但不影响值的类型。
    • @Bergi 哪些函数不继承自 Function.prptotype?我还说“可以使用 () 运算符调用函数,因为 javascript 引擎知道它是使用函数关键字声明的,并且它继承自 Function.prototype 并具有可执行代码”,这不仅是因为它继承自 Function.prototype。
    • var f = Object.setPrototypeOf(function() {…}, null); f() 例如。是的,您没有说“仅因为”,而是说“因为”-继承与是否可以调用完全无关。 “有可执行代码”是唯一的标准。
    • @Bergi 感谢您的解释。我已经相应地编辑了答案。
    【解决方案5】:

    您似乎对“对象”(数据结构)和Object(函数)感到困惑。

    对象是 JavaScript 中的一个概念,它是一些数据的通用容器。对象包含带有键和关联值的属性。

    在 JavaScript 中,所有不是 primitive 的东西都是对象。这包括函数,它们基本上是一种特殊类型的对象,可以使用() 语法“调用”。

    JavaScript 提供了许多具有不同用途的内置函数。两个这样的函数恰好被称为ObjectFunction。所以换句话说,Object 是一个函数,因此也是一个“对象”(数据结构)。

    我们以你的函数Foo为例:

    function Foo() {
        var a = "3";
    }
    

    Foo 是一个函数。这意味着可以调用Foo,例如。 var f = Foo()。在这种情况下,f 将是 undefined,因为 Foo 不会返回任何内容。

    因为Foo是一个函数,它也是一个对象。这意味着我们也可以从中添加和读取属性:

    Foo.bar = 5;
    Foo.bar++;
    console.log(Foo.bar); // prints 6
    

    请注意Foo 的这个“对象”部分与函数的内容无关。这意味着您声明的代码 (var a = "3") 是无关紧要的。您无法在此处以任何方式访问var a,因为在您调用该函数之前它不存在。如果您要执行Foo.a,那么您不会在函数内部操作var a;您正在使用对象 Foo 上的属性 a

    但是,您可以反过来访问函数内部 Foo 的属性:

    function Foo() {
        var a = "3"; // a is local to this scope, you cannot get to it from outside
        console.log(a); // prints 3 - local variable a is accessible inside the scope of this function
        console.log(Foo.a); // prints 5 - a is a property on object Foo, and is accessible here
    }
    // var a inside Foo cannot be accessed here
    Foo.a = 5;
    Foo();
    

    编辑:回复。您关于 cmets 中“this”的问题。 this 是 JavaScript 中的一个特殊关键字,它指代一个对象。然而,这个对象不是函数本身,它是当你使用new关键字调用函数时创建的一个新对象:

    function Bar() {
        this.a = 10;
        console.log(this == Bar); // prints false
    }
    var bar = new Bar();
    console.log(bar.a); // prints 10
    

    使用new 关键字调用的函数称为“构造函数”。 ObjectFunction 都是构造函数的示例,这就是为什么它们的名称以大写字母开头(JavaScript 中的约定)。

    当您使用构造函数创建对象时,该函数的属性prototype 用作创建对象的原型(可通过__proto__ 访问)。

    console.log(bar.constructor == Bar) // prints true
    console.log(bar.__proto__ == Bar.prototype) // prints true
    

    this 也用于其他事情,但这是一个广泛的主题,超出了本问题的范围。

    【讨论】:

    • @TiiJ7 我有一个小疑问,如果我这样做typeof(Function.prototype),输出:“功能”。它只是指 Function.prototype.constructor 吗?
    • @vikrant prototype 只是函数Function 的一个属性。显然它被定义为一个函数本身。对象的属性中可以有函数,因为Function 是一个函数(因此也是一个对象),所以它也适用于此。我不知道他们为什么决定让Function.prototype 也成为一个函数,但这并不重要,因为函数可以做任何对象可以做的事情。
    • 感谢您的回答,我确实检查了 ECMAScript 规范,他们提到了一个原因,因为“函数原型对象被指定为函数对象,以确保与之前创建的 ECMAScript 代码兼容符合 ECMAScript 2015 规范。” tc39.github.io/ecma262/#sec-function-instances-prototype
    【解决方案6】:

    是的,Object 是函数类型。它是一个类/函数实现,当使用 new (new Object()) 调用时,将产生一个分配内存的对象。

    【讨论】:

      【解决方案7】:

      ECMAScript 参考非常适合回答此类问题。

      因此,回答您的问题:Foo 只能是一个对象(因为菜单上的其他所有内容都是基本值类型)。因此,Foo() 是一种特殊语法,它简单地调用该对象的内部 Call 方法。但是Foo 本身就是一个彻头彻尾的对象,你可以用它做任何你可以用任何其他对象做的事情,包括在它上面设置任意属性。

      在对象上定义方法仅仅意味着有一个具有该名称的属性,并且该属性引用了一个对象,而该对象恰好是“函数对象”。

      同样,可以用作构造函数的东西只是一个对象,它恰好有一个 Construct 内部方法,以及调用它的语法糖。

      如你所知,JavaScript 中没有类,它是一种基于原型的面向对象的语言(它就像你能得到的那样object 面向对象,它实际上没有别的东西)。所以任何一种“原型”都只是对象之间的链接。构造函数方法(如上面给出的链接中所解释的)只需调用构造函数方法,并将调用它的对象(即类似String)作为参数,就像语言会用@987654331 调用Call @ 是调用该方法的对象。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-12-11
        相关资源
        最近更新 更多