Серия Relearn JS: рассказ о новом операторе

внешний интерфейс JavaScript

Это первая статья из серии о повторном изучении JS.Первоначальная цель написания этой серии — закрепить мою основу JS. Поскольку это повторное обучение, я определенно не буду вводить точку знаний с нуля.Если вы столкнетесь с каким-либо контентом, который вы не можете понять, пожалуйста, найдите информацию самостоятельно.

Роль новых

Давайте сначала разберемся на двух примерахnewроль

function Test(name) {
  this.name = name
}
Test.prototype.sayName = function () {
    console.log(this.name)
}
const t = new Test('yck')
console.log(t.name) // 'yck'
t.sayName() // 'yck'

Из приведенного выше примера мы можем сделать следующие выводы:

  • newчерез конструкторTestСозданный экземпляр может получить доступ к свойствам в конструкторе
  • newчерез конструкторTestСозданный экземпляр может получить доступ к свойствам в цепочке прототипов конструктора, то есть черезnewОператор, экземпляр и конструктор связаны цепочкой прототипов

Но текущий конструкторTestне явноreturnлюбое значение (возвращает по умолчаниюundefined), что произойдет, если мы позволим ему вернуть значение?

function Test(name) {
  this.name = name
  return 1
}
const t = new Test('yck')
console.log(t.name) // 'yck'

Хотя конструктор в приведенном выше примере возвращает1, но это возвращаемое значение бесполезно, и результат точно такой же, как и в предыдущем примере.

Тогда на этом примере мы можем сделать вывод:

  • Если конструктор возвращает примитивное значение (хотя в примере возвращается только 1, но вы можете попробовать и другие примитивные значения, результат все тот же), то возвращаемое значение бессмысленно

После попытки вернуть исходное значение давайте попробуем, что происходит с возвращенным объектом.

function Test(name) {
  this.name = name
  console.log(this) // Test { name: 'yck' }
  return { age: 26 }
}
const t = new Test('yck')
console.log(t) // { age: 26 }
console.log(t.name) // 'undefined'

На этом примере мы можем обнаружить, что хотя внутреннийthisОн по-прежнему работает нормально, но когда возвращаемое значение является объектом, возвращаемое значение будет возвращено в обычном режиме.

Затем на этом примере мы еще раз делаем вывод:

  • Если возвращаемое значение конструктора является объектом, то возвращаемое значение будет использоваться как обычно.

Эти два примера говорят нам о том, что конструкторы стараются не возвращать значения. Поскольку возврат исходного значения не имеет никакого эффекта, возврат объекта делает новый оператор бесполезным.

Благодаря приведенным выше примерам я считаю, что у всех есть общее пониманиеnewРоль оператора, попробуем реализовать самиnewоператор.

Реализуйте новый оператор самостоятельно

Во-первых, давайте рассмотримnewНесколько функций операторов

  • newОператор возвращает объект, поэтому нам нужно создать объект внутри
  • Этот объект, то есть в конструктореthis, к которому можно получить доступ для монтирования вthisлюбой атрибут на
  • Этот объект имеет доступ к свойствам прототипа конструктора, поэтому вам нужно связать объект с конструктором.
  • Возврат исходного значения необходимо игнорировать, а возвращаемый объект должен обрабатываться в обычном режиме.

Изучив эти функции, мы можем приступить к реализации функции

function create(Con, ...args) {
  let obj = {}
  Object.setPrototypeOf(obj, Con.prototype)
  let result = Con.apply(obj, args)
  return result instanceof Object ? result : obj
}

Это полный код реализации, мы реализовали его с помощью следующих шагов:

  1. Во-первых, функция принимает переменное количество параметров, первый параметр — это конструктор, а следующие параметры использует конструктор.
  2. Затем создайте пустой объект внутриobj
  3. так какobjОбъектам нужен доступ к свойствам в цепочке прототипов конструктора, поэтому мы передаемsetPrototypeOfСоедините два. Этот код эквивалентенobj.__proto__ = Con.prototype
  4. будетobjПривязать к конструктору и передать остальные параметры
  5. Определите, является ли возвращаемое конструктором значение объектом, если это объект, используйте значение, возвращаемое конструктором, в противном случае используйтеobj, тем самым игнорируя исходное значение, возвращаемое конструктором

Далее давайте воспользуемся функцией, чтобы увидеть, такое ли поведение, какnewоператор согласован

function Test(name, age) {
  this.name = name
  this.age = age
}
Test.prototype.sayName = function () {
    console.log(this.name)
}
const a = create(Test, 'yck', 26)
console.log(a.name) // 'yck'
console.log(a.age) // 26
a.sayName() // 'yck'

Хотя код реализации состоит всего из нескольких строк, результат отличный

Наконец

Мы заново узнали через эту статьюnewОператор, если у вас есть какие-либо вопросы, пожалуйста, свяжитесь со мной в области комментариев.

Все мои циклы статей будут в моемGithubОн обновляется первым, и желающие могут обратить на него внимание. В этом году я в основном перепишу следующие три столбца.

  • Переучи JS
  • Реагировать продвинуто
  • Переопределить компонент

Наконец, если вы считаете, что контент полезен, вы можете обратить внимание на мой официальный аккаунт «Внешняя часть действительно забавная», вас ждет много хорошего.