console.log(main2.second) // undefined
Тут вы выбираете свойство объекта и только. Объектом будет являться конструктор, а не инстанс типа, пораждаемый этим конструктором.
updated
Для начала давайте определимся с такой вещью, что в JS все является объектом (с примитивными типами чуть сложнее но это сейчас не важно).
Объекты имеют определенный тип. Вы можете создать новый тип, объявив конструктор типов:
function MyType() {
}
Соответственно когда мы создаем инстанс объекта этого типа будет работать следующее:
var obj = new MyType();
obj instanceof MyType; // true
obj instanceof Object; // true
({}) instanceof Object; // true
({}) instanceof MyType; // false
Причем магия тут в том, что функции (а конструктор это просто функция с именем) - это тоже объект
MyType instanceof MyType; // false
(function() {}) instanceof Function; // true
(function() {}) instanceof Object; // true
То есть запись вида:
main2.second
мы должны читать как "возьми свойство second у объекта main2, который является функцией". Мы просто не вызываем эту функцию. Мы просто обращаемся к свойству функции.
На этом можно было бы остановиться, поскольку это и является ответом на ваш вопрос, но давайте еще чуть поговорим про this.
В отличии от языков вроде java мы можем менять "контекст" вызова функций. Достаточно сделать так:
function Foo() {
this.val = 'foo';
}
Foo.prototype.bar = function () {
return this.val;
};
var obj = new Foo();
var fake = {
val: 'fake',
// это просто функция, она является объетом,
// так что мы можем просто присвоить значение
bar: obj.bar,
};
fake.bar(); // fake;
То есть контекст вызова это просто указание на объект, которому пренадлежит функция в момент ее вызова. Если мы объявим функцию в глобальной области видимости, this будет указывать на window как на контекст вызова.
Далее думаю продолжать нет смысла. Лучше проштудируйте что-нибудь в этом духе:
https://learn.javascript.ru/objects-more