Является ли 'Object' функцией в JavaScript?
Рассмотрим эту функцию:
function Foo(){
var a = "3";
};
Согласно __proto__ VS. прототип в JavaScript,
Foo.__proto__ = Function.prototype
Function.prototype.__proto__ = Object.prototype
Я понял эту часть, но если я сделаю это в консоли Google Chrome:
Object.__proto__
output: ƒ () { /* native code */ }
Function.__proto__
output: ƒ () { /* native code */ }
Q1: почему они указывают на функцию? Что на самом деле представляют собой Function
и Object
и чем они отличаются друг от друга, потому что Объект на самом деле является функцией?
typeof Object
"function"
Q2: Если в JavaScript все является объектом, то почему Object
является функцией? Кроме того, как функция на самом деле реализована внутри JavaScript? Что происходит с переменными, объявленными внутри функции? Функция преобразована в объект компилятором JavaScript?
Извините, если я упускаю что-то очевидное. Я действительно смущен тем, как функция и объект реализованы в JavaScript.
Ответы
Ответ 1
Вы, кажется, запутались между "объектом" (структура данных) и Object
(функция).
Объект - это концепция в JavaScript, которая является универсальным контейнером для некоторых данных. Объект содержит свойства с ключами и соответствующими значениями.
В JavaScript все, что не является примитивом, является объектом. Это включает в себя функции, которые в основном представляют собой особый тип объекта, который можно "вызывать" с помощью синтаксиса ()
.
JavaScript предоставляет ряд встроенных функций различного назначения. Две такие функции называются Object
и Function
. Другими словами, 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
внутри функции; вы работаете со свойством a
над объектом Foo
.
Однако вы можете сделать это наоборот и получить доступ к свойствам в 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();
Редактировать: Re. Ваш вопрос по поводу "этого" в комментариях. 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
ключевым словом, называется "функцией конструктора". Object
и Function
являются примерами функций-конструкторов, поэтому их имена начинаются с заглавной буквы (соглашение в JavaScript).
Когда вы создаете объект с помощью функции конструктора, prototype
свойства этой функции используется в качестве прототипа (доступного через __proto__
) созданного объекта.
console.log(bar.constructor == Bar) // prints true
console.log(bar.__proto__ == Bar.prototype) // prints true
this
также используется для других вещей, но это широкая тема и выход за рамки этого вопроса.
Ответ 2
Function и Object являются функциями-конструкторами, которые могут использоваться для создания функции и объекта, соответственно, что является причиной typeof Function
возвращает function
.
О том, как функции и объекты связаны в JavaScript, рассмотрим следующие моменты:
- Все не примитивные типы являются объектами в JavaScript.
- Все объекты прямо или косвенно наследуются от Object.prototype (если прототип не изменен явно с помощью setPrototypeOf).
- Все нативные функции наследуются от Function.prototype, который наследуется от Object.prototype, поэтому это означает, что функция косвенно наследуется от Object.prototype, потому что функции рассматриваются как объекты в JavaScript.
- Причиной того, что функции рассматриваются как объекты, является то, что они могут передаваться в качестве параметров другим функциям и могут быть возвращены из функций, то есть функций более высокого порядка (мощная функция javascript).
-
Функцию можно вызывать с помощью оператора ()
поскольку механизм JavaScript знает, что она объявлена с использованием ключевого слова функции, и имеет исполняемый код. Таким образом, всякий раз, когда он вызывается, движок JavaScript создает новый контекст выполнения и устанавливает привязку this
а затем выполняет функцию. Ничего из этого не происходит, когда вы пытаетесь вызвать объект, вместо этого выдается ошибка, т.е. "Это не функция".
Таким образом, мы можем сказать, что не каждый объект является функцией, потому что они, возможно, не были объявлены с использованием ключевого слова function и не имеют исполняемого кода.
- Так как функция рассматривается в JavaScript как объект, мы можем добавлять к ней свойства, создавать из нее новые объекты.
- Объект нефункционального типа нельзя вызвать с помощью
()
поскольку он не имеет исполняемого кода и не объявлен с использованием ключевого слова function. Вместо этого он объявляется с использованием new Object()
или нотации объекта и содержит методы и свойства.
Я надеюсь, что это очищает оба вопроса.
Ответ 3
Q1: почему они указывают на функцию?
A1: потому что они функции. Function
и Object
- просто функции конструктора.
Функция является Function object
. объект является Object object
.
Q2: Если в JavaScript все является объектом, то почему Object
является функцией?
A2: Потому что Object
это просто функция конструктора.
typeof Object
// 'function'
typeof new Object()
// 'object'
И функция является экземпляром Function
, так что делает функцию объектом.
(function(){}) instanceof Function
// true
Ответ 4
В корне
Functions
имеют некоторый код, который может быть выполнен.
Object
- это те, которые содержат данные.
Для класса Point
имеющего x
и y
.
class Point {
constructor(x, y) {
this.x = x;
this.y = y;
}
isOrigin() { return x == 0 && y == 0; }
}
let p = new Point();
Ответ 1
В этом случае p
является object
который содержит данные или другие функции.
p.isOrigin
является функцией.
Точно так же класс Point
сам по себе является function
которая при запуске выдает p
. Вот почему все классы, такие как Object
и Functions
являются functions
точнее constructor functions
.
Ответ 2
Если в JavaScript все является объектом, то почему Object
является функцией?
То же, что ответ 1.
Кроме того, как функция на самом деле реализована внутри JavaScript?
Различные движки JavaScript будут иметь разные реализации. У них есть спецификации, которым они должны следовать.
Что происходит с переменными, объявленными внутри функции?
Не по теме. Каждая function
выполняется с областью, которая содержит все данные для этих функций.
Функция преобразована в объект компилятором JavaScript?
Не уверен, что ты спрашиваешь.
Ответ 5
Справочник по ECMAScript очень хорош для ответов на такие вопросы.
- https://www.ecma-international.org/ecma-262/9.0/index.html#sec-ecmascript-language-types - это точка входа о том, какие типы поддерживает язык, и вводится понятие, что все, что есть, является либо довольно стандартное значение (логическое значение, строка и т.д.), либо объект. Но никаких дальнейших типов.
- https://www.ecma-international.org/ecma-262/9.0/index.html#sec-object-type объясняет тип объекта. По сути, это набор атрибутов и/или методов доступа (например, getter/setter). Это также вводит термин "функциональный объект".
- https://www.ecma-international.org/ecma-262/9.0/index.html#sec-object-internal-methods-and-internal-slots показывает внутреннюю семантику, внутренние методы и т.д. объектов. В конце этого раздела, в частности, описаны специфические внутренние элементы "функционального объекта" ("Call" и "Construct"), включая небольшие детали, такие как конструктор, являющийся необязательным.
Следовательно, чтобы ответить на ваш вопрос: Foo
может быть ничем иным, как объектом (потому что все остальное в меню является базовым типом значения). Следовательно, Foo()
- это специальный синтаксис, который просто вызывает внутренний метод Call
этого объекта. Но Foo
сам по себе является объектом насквозь, вы можете делать с ним все остальное, что вы можете делать с любым другим объектом, включая установку на него произвольных атрибутов.
Наличие метода, определенного для объекта, просто означает, что существует атрибут с этим именем, и этот атрибут ссылается на объект, который оказывается "функциональным объектом".
Что-то, что можно использовать в качестве конструктора, опять же, просто объект, у которого есть внутренний метод Construct
и синтаксический сахар для его вызова.
Как вы знаете, в JavaScript нет классов, это объектно-ориентированный язык, основанный на прототипах (он настолько объектно-ориентирован, насколько вы можете понять, в нем буквально больше ничего нет). Таким образом, любой "прототип" - это просто связь между объектами. Метод конструктора (как объяснено в приведенной выше ссылке) просто вызывает метод конструктора с объектом, для которого он был вызван (т.е. Что-то вроде String
), в качестве аргумента, точно так же, как язык будет вызывать Call
при this
объект является методом был вызван на.
Ответ 6
Object
является функцией конструктора всех объектов. Итак, typeof Object==="function"
Вот фрагмент для визуализации:
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()
Ответ 7
Да, объект имеет тип функции. Это реализация класса/функции, которая при вызове с new (new Object()
) приводит к объекту с выделенной памятью.