Почему функции кажутся объектами? - PullRequest
0 голосов
/ 17 апреля 2020

Я пытаюсь изучать JS / ES и немного запутался в классах и объектах.

Два приведенных ниже фрагмента кода делают абсолютно то же самое, но последний явно использует класс. Но каково первое использование? Я думал, что класс стал объектом при выполнении?

Я бы ожидал, что clock будет функцией, но, очевидно, его можно использовать как объект. Почему это так?

И почему кому-то захочется использовать классовый способ, когда первый короче набирать?

var clock = {
  start() {
    setInterval(() => console.log(Date()), 1000) 
  }
}
clock.start()

и

class Clock {
  start() {
    setInterval(() => console.log(Date()), 1000)
  }
}
const c = new Clock
c.start()

1 Ответ

3 голосов
/ 17 апреля 2020

Классы - это шаблоны для объектов. Они описывают, как ведут себя объекты. В javascript, new Clock() - это способ получения нового объекта класса Clock.

. Синтаксис литерала объекта ({foo: 'bar'}) ярлык для создания универсального c объекта. Таким образом, класс объекта, созданного таким образом, равен Object. Кроме того, создание объекта таким способом не позволяет создавать new объекты с одинаковым поведением (что в некотором смысле означало бы, что они принадлежат к одному и тому же классу).

В некоторых языках, таких как C ++ и Java, классы являются фундаментальными строительными блоками языка. Но в javascript это просто концепция, и в основном означает (неформально) любой объект с таким же заданным поведением. Более формально, хотя это объект, который имеет прототип класса в своей цепочке прототипов. Что такое прототипы и прототипы цепей? Ну, каждый * объект (даже созданный с использованием буквального синтаксиса объекта) имеет прототип как скрытое ** свойство. При поиске свойства в объекте, если оно не найдено в самом объекте, оно ищет свойство в прототипе. И если этот объект-прототип не имеет этого свойства, он идет «вверх по цепочке» и проверяет прототип прототипа на наличие свойства и продолжает делать это настолько далеко, насколько это возможно.

Когда вы используете class синтаксис, вы устанавливаете свойства в прототипе для каждого объекта, который создает класс. Итак, в вашем примере вы назначаете прототипу функцию start для каждого объекта Clock. Но если вы назначаете его самому объекту, то он не использует прототип.

Интересно, что классы также являются объектами (они могут иметь свойства и методы).

Официальную документацию см. Здесь:

*: Вы можете сделать объект без прототипа, используя Object.create(null), но это редко. Преимущество этого состоит в том, что вы не можете случайно получить доступ к свойствам прототипа, потому что их нет.

**: Иногда вы можете получить доступ к прототипу, используя устаревшее свойство __poto__. Предпочтительный новый способ - Object.getPrototypeOf(object)

Вот несколько примеров, которые вы можете изучить:

const clockByLiteral = { start(){/* do something */} }
function startClock () { /* do something */}
class Clock {
  start() { /* do something */}
}

const clock1 = new Clock()
const clock2 = new Clock()

function getClassName(object){
  return object.constructor.name
}
console.log('"class" of clockByLiteral:', getClassName(clockByLiteral))
console.log('"class" of clockByLiteral.start:', getClassName(clockByLiteral.start))
console.log('"class" of startClock:', getClassName(startClock))
console.log('"class" of Clock class:', getClassName(Clock))
console.log('"class" of clock1:', getClassName(clock1))
console.log('"class" of clock2:', getClassName(clock2))
console.log('is the constructor of clock1 Clock?:', clock1.constructor === Clock, "(meaning that classes and constructors are the same objects, and are functions also")
console.log('is the prototype of clock1 Clock.prototype?:', Object.getPrototypeOf(clock1) === Clock.prototype)


console.log('is clock1 the same object as clock2?:', clock1 === clock2)
console.log('is clock1.start the same as clock2.start?:', clock1.start === clock2.start)
console.log('is clock1.start the same as Clock.prototype.start?:', clock1.start === Clock.prototype.start)

console.log('is clock1 an "instance" of Clock?:', clock1 instanceof Clock)
console.log('is clock1 an "instance" of Object?:', clock1 instanceof Object)
console.log('is clock1 an "instance" of Function?:', clock1 instanceof Function)
console.log('is Clock an "instance" of Function?:', Clock instanceof Function)
console.log('is startClock an "instance" of Function?:', Clock instanceof Function)
console.log('is startClock an "instance" of Object?:', Clock instanceof Object)
...