Вызов функции-конструктора | почему это ключевое слово возвращает значение undefined?

Я играю с объектами и конструкторами, и мне любопытно, почему я не могу выполнить: person(5,10). Параметры передаются функции человека, но затем назначение переменной исчезает, и я получаю сообщение об ошибке «невозможно установить свойство« возраст »неопределенного» в chrome.

"use strict"

function person(age, height){
this.age = age;
this.height = height;
this.calculate = function(){
     var newHeight = this.height * 2;
     console.log(newHeight);
    }
}
person(5,10);

person Stu    schedule 18.11.2015    source источник
comment
используйте 1_   -  person Sagi    schedule 19.11.2015
comment
Вам нужно инициализировать объект   -  person Sterling Archer    schedule 19.11.2015
comment
Чтобы использовать функцию в качестве конструктора, вы должны вызвать ее с помощью оператора new. Это сработает для нового человека (5,10);   -  person 11thdimension    schedule 19.11.2015
comment
@ 11thdimension знаете ли вы, почему вы не можете просто выполнить его, как я написал? Я не пытаюсь создать новый объект, я просто заметил, что не могу запустить код, как написано. Мне кажется, что человек является допустимым определением функции, и поэтому человек (5,10) должен вывести 20 на консоль. Спасибо.   -  person Stu    schedule 19.11.2015
comment
Мне кажется, что person является допустимым определением функции, и поэтому person(5,10) должен вывести в консоль 20. Как вы думаете, что делает this.age = age? Как вы думаете, что такое this? Почему вы ожидаете, что функция будет что-то регистрировать? Он не содержит оператора console.log. console.log находится в теле, если внутренняя функция никогда не вызывается. Я не пытаюсь создать новый объект, но вы только что сказали в своем вопросе: Я играю с объектами и конструкторами.   -  person Felix Kling    schedule 19.11.2015
comment
@FelixKling Я думаю, что this.age относится к объекту window, и если это правда (что может быть не так), this не должно оцениваться как undefined (я думаю). Однако, если бы это был объект окна, window.age было бы undefined, что имело бы смысл. Спасибо, что поймали часть console.log.   -  person Stu    schedule 19.11.2015
comment
Я думаю, что this.age относится к объекту окна Я думаю, вы имеете в виду, что this является объектом window. Как я сказал в своем ответе, если ваш код работает в строгом режиме, this равно undefined. И поскольку вы получаете эту конкретную ошибку, похоже, ваш код работает в строгом режиме. Однако, если бы это был объект окна, значение window.age было бы неопределенным, что имело бы смысл. Что ж, после запуска вашей функции window.age будет равно 5.   -  person Felix Kling    schedule 19.11.2015
comment
@Stu, посмотри мой ответ ниже для объяснения.   -  person 11thdimension    schedule 19.11.2015


Ответы (2)


Путаница возникает из-за того, что функцию можно использовать и как вызываемую функцию, и как конструктор объекта. Хорошей практикой является не смешивать обе формы, то есть функцию-конструктор не следует использовать в качестве вызываемой функции. В общем случае функция-конструктор имеет первую букву с заглавной буквы (просто по соглашению, чтобы дать подсказку читателю кода). Объектно-ориентированные языки обычно неявно предоставляют ссылку на объект, для которого вызывается метод. В Javascript эта ссылка является ключевым словом this внутри функции. Рассмотрим следующий код.

var obj = {
    sum: 0,
    add: function(increment) {
        this.sum += increment;
        return this.sum;
    }
};

Когда мы вызываем obj.add(2), интерпретатор или компилятор на любом другом объектно-ориентированном языке будет выполнять внутренний вызов метода add следующим образом:

add(arguments..., [this=obj]) {
    //this is the obj reference inside the method
}
add(arguments, obj);

Выше приведен только псевдокод, последний параметр скрыт от нас, и нам не нужно передавать его явно, этот параметр является ссылкой на фактический объект, для которого был вызван метод add(), и доступен через «этот» keyworkd .

В общем, когда мы объявляем функцию вне области видимости объекта, она становится методом (отредактированным**, если он не вложен в другую функцию) глобального объекта (обычно объекта окна). Таким образом, его вызов будет передавать глобальный объект как ссылку "this". В строгом режиме глобальный объект по умолчанию не определен, и любые операции, которые должны выполняться с окном или глобальным объектом, должны выполняться явно. Чтобы мы случайно не изменили глобальный объект.

Когда мы вызываем функцию как конструктор, как показано ниже

var p1 = new Person();

Интерпретатор выполнит код, аналогичный

var newObj = new Object();
Person(arguments..., [this=newObj]) {
    //this is the newObj reference inside the method
    return this;
}
Person(arugments..., newObj);

Надеюсь, теперь стало немного понятнее.

person 11thdimension    schedule 18.11.2015
comment
Спасибо, что нашли время, чтобы создать такой хороший ответ. Это определенно помогает. Я использовал строгий режим, я просто не осознавал этого, потому что скопировал и вставил свой код в существующий документ. - person Stu; 19.11.2015
comment
В общем случае, когда мы объявляем функцию вне области видимости объекта, она становится методом глобального объекта (обычно объекта окна). Таким образом, его вызов будет передавать глобальный объект как ссылку this. Это неверно. Просто подумайте о вложенных функциях: function foo() { function bar() { console.log(this); }; bar();}; foo(). bar не является глобальным, это не свойство глобального объекта, а this относится к глобальному объекту. В строгом режиме глобальный объект по умолчанию не определен Нет, глобальный объект всегда является объектом. В строгом режиме this по умолчанию не является глобальным объектом. - person Felix Kling; 19.11.2015
comment
Это правильный, точный способ сказать, что если функция не вызывается для какого-либо объекта с помощью оператора (точка), она вызывается для глобального объекта. Только функции, которые не содержатся ни в одной другой функции, становятся методами глобального объекта. В любом другом случае (вложенные функции) они просто действуют так, как если бы они вызывались для глобального объекта, не становясь членом глобального объекта. - person 11thdimension; 19.11.2015

Я получаю сообщение об ошибке «невозможно установить свойство «возраст» неопределенного» в chrome.

При вызове функции в строгом режиме this равен undefined. Кажется, вы хотите вызвать функцию как конструктор с new:

new person(5, 10)

Подробнее о конструкторах.


Примечание. По соглашению имена функций-конструкторов пишутся с заглавной буквы.

person Felix Kling    schedule 18.11.2015
comment
Хорошо, что он использует строгий режим, иначе он бы даже не заметил ошибку :-) - person Bergi; 19.11.2015