Какие значения может вернуть конструктор, чтобы избежать возврата?

Каковы точные обстоятельства, при которых оператор return в Javascript может возвращать значение, отличное от this, когда конструктор вызывается с использованием ключевого слова new?

Пример:

function Foo () {
  return something;
}

var foo = new Foo ();

Если я не ошибаюсь, если something является нефункциональным примитивом, возвращается this. В противном случае возвращается something. Правильно ли это?

IOW, какие значения могут something принимать, чтобы вызвать (new Foo () instanceof Foo) === false?

Ответ 1

Точное условие описано во внутреннем свойстве [[Construct]], которое используется оператором new :

Из ECMA-262 3-й. Спецификация издания:

13.2.2 [[Construct]]

Когда свойство [[Construct]] для объекта Function F имеет значение вызваны следующие шаги:

  1. Создайте новый собственный объект ECMAScript.
  2. Установите для свойства [[Class]] Result(1) значение "Object".
  3. Получите значение свойства prototype из F.
  4. Если Result(3) является объектом, установите для свойства [[Prototype]] элемента Result(1) значение Result(3).
  5. Если Result(3) не является объектом, установите для свойства [[Prototype]] Result(1) исходный объект-прототип Object как описано в 15.2.3.1.
  6. Вызовите свойство [[Call]] F, указав Result(1) в качестве значения this, и предоставление списка аргументов, переданного в [[Construct]] как значения аргумента.
  7. Если Type(Result(6)) Object затем верните Result(6).
  8. Вернитесь Result(1).

Посмотрите на шаги 7 и 8, новый объект будет возвращен, только если тип Result(6) (значение, возвращаемое конструктором F функция) не является объектом.

Ответ 2

Конкретные примеры http://jsbin.com/zivivucahi/1/edit?html,js,console,output

/*
ECMA 262 v 5
http://www.ecma-international.org/publications/files/ECMA-ST/Ecma-262.pdf
"4.3.2
primitive value
member of one of the types Undefined, Null, Boolean, Number, Symbol, or String as defined in clause 6"
*/

var Person = function(x){
  return x;

};


console.log(Person.constructor);
console.log(Person.prototype.constructor);
console.log(typeof(Person));
console.log(typeof(Person.prototype));

function log(x){
  console.log(x instanceof Person);
  console.log(typeof x);
  console.log(typeof x.prototype);
}

log(new Person(undefined));
log(new Person(null));
log(new Person(true));
log(new Person(2));
log(new Person(""));

//returns a function not an object
log(new Person(function(){}));


//implementation?
//log(new Person(Symbol('%')));

Ответ 3

Я не мог найти никакой документации по этому вопросу, но я думаю, что вы правы. Например, вы можете вернуть new Number(5) из конструктора, но не буквенный 5 (который игнорируется, а this возвращается вместо этого).

Ответ 4

Попытка выразить несколько слов более простыми словами.

В JavaScript, когда вы используете ключевое слово new для функции и если

  1. функция ничего не возвращает, она вернет намеченный объект

function User() {
  this.name = 'Virat'
}

var user = new User();
console.log(user.name); //=> 'Virat'

Ответ 5

В качестве побочного примечания возвращаемое значение или this является лишь частью уравнения.

Например, рассмотрим следующее:

function Two() { return new Number(2); }
var two = new Two;
two + 2; // 4
two.valueOf = function() { return 3; }
two + 2; // 5
two.valueOf = function() { return '2'; }
two + 2; // '22'

Как вы можете видеть, .valueOf() используется внутри и может использоваться для удовольствия и прибыли. Вы даже можете создавать побочные эффекты, например:

function AutoIncrementingNumber(start) {
    var n = new Number, val = start || 0;
    n.valueOf = function() { return val++; };
    return n;
}
var auto = new AutoIncrementingNumber(42);
auto + 1; // 43
auto + 1; // 44
auto + 1; // 45

Я могу себе представить, что это должно иметь какое-то практическое применение. И это не обязательно должно быть явно Number, если вы добавите .valueOf к любому объекту, который может вести себя как число:

({valueOf: function() { return Math.random(); }}) + 1; // 1.6451723610516638

Вы можете использовать это, чтобы создать объект, который всегда возвращает новый GUID, например.

Ответ 6

Когда вы используете ключевое слово new, создается объект. Затем вызывается функция для инициализации объекта.

Нет ничего, что могла бы сделать функция, чтобы предотвратить создание объекта, как это делается до вызова функции.