Javascript-форум (https://javascript.ru/forum/)
-   Общие вопросы Javascript (https://javascript.ru/forum/misc/)
-   -   Функции-конструкторы в JS (https://javascript.ru/forum/misc/76470-funkcii-konstruktory-v-js.html)

Начинающий-Js-кодер 14.01.2019 20:02

Функции-конструкторы в JS
 
Сейчас изучаю конструкторы, прототипы и у одной небезызвестной библиотеки встретил такого плана код:
new go.Binding("points").makeTwoWay()

если как сделать
new MyClass();
я понимаю,код вот:
function MyClassl(name) {
  this.name = name;
  this.canWalk = true;
}

var animal = new MyClass();
, то как сделать
new MyClass.Module1();
не понимаю, пробовал вот так:
function MyClass() {
  // вспомогательная переменная
  var phrase = "Привет";

  this.Module1 = function() {
    alert( phrase ); // использование
  };
}

new MyClass.Module1();

так не работает, пробовал так:
function MyClass() {

  this.prm = "test1";
function Module1() {
      return "Module1";
    }
  return { Module1: Module1 };  
}
при вызове
alert( new MyClass.Module1() );
ничего не срабатывает.

И видел, что некоторые делают еще так:
new go.Binding("points").makeTwoWay(),

На сайте в разделе по конструкторам не нашел такое, и хотело бы узнать, зачем делаются три такие конструкции и как они так делаются, что можно вызвать new MyClass.Module1.Submodule1;

j0hnik 14.01.2019 20:18

function MyClass() {
  this.canWalk = true;
}
MyClass.prototype.Module1 = function() {
	alert( 'Привет' );
};

var animal = new MyClass();
animal.Module1();

Начинающий-Js-кодер 14.01.2019 20:39

А почему вот так: new MyClass.Module1 код который вы показали не запускается?
И как быть для остальных видов запуска или там аналогично?

j0hnik 14.01.2019 20:41

function MyClass() {
  this.canWalk = true;
}
MyClass.prototype.Module1 = function() {
	alert( 'Привет' );
};

new MyClass().Module1();


все запускается

Начинающий-Js-кодер 14.01.2019 20:45

а если так:new MyClass.Module1; то не работает

j0hnik 14.01.2019 20:48

Цитата:

Сообщение от Начинающий-Js-кодер
а если так:new MyClass.Module1; то не работает

методы вызываются скобками
так вы можете просто посмотреть console.log(new MyClass.Module1)

Malleys 14.01.2019 20:49

function MyClass() {}

MyClass.Module1 = function Module1() {
	var phrase = "Привет";
	alert(phrase);
}

new MyClass.Module1();


function MyClass() {
	this.prm = "test1";
}

MyClass.Module1 = function Module1() {
	return Object(new MyClass().prm);
}

alert(new MyClass.Module1())


UPD
Цитата:

Сообщение от j0hnik
все запускается

То, что вы метод назвали как в C#, никак его автомагический не сделает классом. Вы вызываете метод, а не класс.

UPD2
Цитата:

Сообщение от Начинающий-Js-кодер
а если так:new MyClass.Module1; то не работает

Вообще-то работает,
function MyClass() {
	this.prm = "test1";
}

MyClass.Module1 = function Module1() {
	return Object(new MyClass().prm);
}

alert(new MyClass.Module1)

Начинающий-Js-кодер 14.01.2019 21:14

Работает да, потому что сделали так:
MyClass.Module1 = function Module1() {...}
то есть имя метода совпадает с именем функции этого метода. Я такого не встречал раньше, так разве можно делать?

j0hnik 14.01.2019 21:16

Цитата:

Сообщение от Malleys
То, что вы метод назвали как в C#, никак его автомагический не сделает классом. Вы вызываете метод, а не класс.

Я и не говорил что это класс

Начинающий-Js-кодер 14.01.2019 21:40

Цитата:

То, что вы метод назвали как в C#, никак его автомагический не сделает классом. Вы вызываете метод, а не класс.
То есть в javascript нет возможности при исполнении такой строки new MyClass.Module1 вызвать именно конструктор new MyClass.Module1 а не MyClass и его метод Module1?
Просто я думал, что new MyClass.Module1 в javascript примерно такое же как и new PHPClass\ClassNamespace\Etc(); в PHP. Это не так, выходит.

Malleys 14.01.2019 21:58

Цитата:

Сообщение от Начинающий-Js-кодер
то есть имя метода совпадает с именем функции этого метода.

На самом деле это статический вложенный класс. Обычно класс называют с большой буквы, а метод с маленькой, иначе можно перепутать статический вложенный класс со статическим методом класса.
Цитата:

Сообщение от Начинающий-Js-кодер
То есть в javascript нет возможности при исполнении такой строки new MyClass.Module1 вызвать именно конструктор new MyClass.Module1 а не MyClass и его метод Module1?

Вот пример статического вложенного класса и статического метода и их всевозможных вызовов... вызовы происходят в порядке чисел alert
function X() {alert(1)}
X.prototype = {
	y: function() {alert(2)}
};
X.y = function() {alert(3)};

X.Y = function Y() {alert(4)}
X.Y.prototype = {
	y: function() {alert(5)}
};
X.Y.y = function() {alert(6)};

new X(); // или new X
new X().y();
X.y();
new X.Y(); // или new X.Y
new X.Y().y();
X.Y.y();


Вот тоже самое, но только с синтаксисом класса... Здесь трудно перепутать вложенный класс со статичным методом класса.
class X {
	constructor(){alert(1)}
	y(){alert(2)}
	static y(){alert(3)}
}

X.Y = class Y {
	constructor(){alert(4)}
	y(){alert(5)}
	static y(){alert(6)}
};

new X(); // или new X
new X().y();
X.y();
new X.Y(); // или new X.Y
new X.Y().y();
X.Y.y();


Синтаксис класса является более предпочтительным в языке программирования JavaScript.

Начинающий-Js-кодер 14.01.2019 22:07

Спасибо за оба примера. Мне по душе 1 вариант написания. Но я так и не понял, а зачем в javascript часто разработчики используют вложенные классы?
И все же в первом варианте у вас используются скобки, а я хотел бы добиться такого вызова: new X.Y;

Malleys 14.01.2019 22:13

Цитата:

Сообщение от Начинающий-Js-кодер
а зачем в javascript часто разработчики используют вложенные классы?

Они, возможно, используют объемлющий класс просто как пространство имен. Или как способ представления данных.

Например, у вас есть класс Field описывающий какое-то абстрактное поле:
class Field {
	constructor(width, length) {
		this.width = width;
		this.length = length;
	}
}


У поля есть заданные и неизменяемые длина и ширина. Теперь у вам необходимо создать класс Point, описывающий какую-либо точку на поле, и вы думаете: точка на поле не отделима от поля, но точка в общем может использоваться ещё где-нибудь, так зачем же создавать глобальную сущность, которая бы не позволила вложить смысл, например, точке в пространстве? И правильно думаете. И делаете вложенный класс...
class Field {
	constructor(width, length) {
		this.width = width;
		this.length = length;
	}
}

Field.Point = class Point {
	constructor(x, y) {
		this.x = x;
		this.y = y;
	}
};


Вложенный класс - способ представления данных. У вас теперь логически один класс в иерархии относится к другому. Т.е. создание полей и точек теперь будет выглядеть так...
const field = new Field(400, 400);
const p = new Field.Point(25, 50);


Теперь все, кто увидят такую иерархию будут понимать, что Point используется вместе с Field.

Цитата:

Сообщение от Начинающий-Js-кодер
И все же в первом варианте у вас используются скобки, а я хотел бы добиться такого вызова: new X.Y

там, где написано new X() или new X.Y() можно сократить до new X или new X.Y соответственно.

Начинающий-Js-кодер 14.01.2019 22:24

Понял теперь. А есть книги в которых об этом пишут? О том как организовывать большие классы, как их правильно структурировать и прочее?


Часовой пояс GMT +3, время: 17:23.