Сравнение двух ситуаций, когда конструктор вызывается без ключевого слова new - PullRequest
0 голосов
/ 27 января 2020

function Person(name, age, gender) {
  this.name = name; // run
}

function PersonSafe(name) {
  if (!(this instanceof arguments.callee))
    return new PersonSafe(name)

  this.name = name; // run
}

var qux = Person('qux');
console.log('Person qux: ', qux);
console.log('[[global]] name: ', name);

var quxSafe = PersonSafe('qux');
console.log('PersonSafe qux: ', quxSafe);

enter image description here

Сравнение двух ситуаций, когда constructor вызывается без ключевого слова new.

Я не знаю почему результаты запуска двух кодов разные .
Функции body Person() и PersonSafe() различны,
но строка (this.name = name;), которую будут выполнять qux и quxSafe, совпадает.
Итак ... Почему результаты отличаются?

Ответы [ 2 ]

2 голосов
/ 27 января 2020

Когда вы вызываете функцию в качестве конструктора (здесь Person), создается объект (пустой объект, внутренний прототип которого является прототипом функции конструктора - здесь Person.prototype), и этот объект то, что было только что создано - это то, на что будет указывать значение this внутри функции. Этот объект также будет неявно возвращен в конце конструктора.

Напротив, когда вы не используете new, такой объект не создается; вы просто вызываете обычную функцию, и значение this внутри нее будет зависеть от вызывающего контекста функции. Здесь, поскольку нет вызывающего контекста (вызываемая функция не является частью объекта), this внутри функции будет либо глобальным объектом (в случае небрежного режима), либо undefined (в случае строгого режима).

Итак, var qux = Person('qux'); запускает this.name = name, где this - глобальный объект.

С PersonSafe вы проверяете, что this экземпляр конструктора (что this имеет внутренний прототип прототипа конструктора) - если вызывать без new, этот тест не пройден, поскольку this будет либо глобальным объектом, либо undefined.

Обратите внимание, что arguments.callee запрещено в строгом режиме, и строгий режим должен почти всегда использоваться. Попробуйте заменить на new.target вместо:

function PersonSafe(name) {
    if(!(new.target))
        return new PersonSafe(name)

    this.name = name; // run
}

var quxSafe = PersonSafe('qux');
console.log('PersonSafe qux: ',quxSafe);
1 голос
/ 27 января 2020

Основная причина, по которой это отличается, связана с ключевым словом «new», которое означает, что функция будет обрабатываться как объект, и ей будет присвоено proto назначенное свойство.

Также эта переменная будет указывать на вновь созданный объект.

Вот хорошее описание: Что такое ключевое слово 'new' в JavaScript?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...