Javascript-форум (https://javascript.ru/forum/)
-   Общие вопросы Javascript (https://javascript.ru/forum/misc/)
-   -   Функция - конструктор Person (https://javascript.ru/forum/misc/77566-funkciya-konstruktor-person.html)

DarkPhoenix 21.05.2019 09:58

Функция - конструктор Person
 
function Person(firstname, lastname, age){
this.firstname = firstname;
this.lastname = lastname;
this.age = age;

}
const person = new Person('Vince', 'Vicked', 55);
console.log(person);

Тут все сделал.
Загвоздка в ограничениях.

- firstname и lastname всегда должны быть строки от 3 до 20 символов, содержащие только латинские буквы
- age всегда должно быть числом в диапазоне (0, 150) включительно
- если что-либо из перечисленного не выполнено, выкиньте ошибку

Куда их вставлять? И через что? if или что другое? Буду рад помощи, или коду. Спасибо

Malleys 21.05.2019 11:44

Вариант №1
class Person {
	constructor(firstName, lastName, age) {
		this.firstName = firstName;
		this.lastName = lastName;
		this.age = age;

		Object.freeze(this);
	}

	set firstName(value) {
		if(value instanceof String === false && typeof value !== "string")
			throw new TypeError(`No instance for ‘${Object(value).constructor.name}’ arising from a use of ‘firstName’`);

		if(value.length < 3 || value.length > 20)
			throw new RangeError(`Invalid first name length`);

		if(!/^[a-zçéäëïöü'’‘–—-]{3,20}$/i.test(value))
			throw new Error(`Invalid first name`);

		this._firstName = value;
	}

	get firstName() {
		return this._firstName;
	}

	set lastName(value) {
		if(value instanceof String === false && typeof value !== "string")
			throw new TypeError(`No instance for ‘${Object(value).constructor.name}’ arising from a use of ‘lastName’`);

		if(value.length < 3 || value.length > 20)
			throw new RangeError(`Invalid last name length`);

		if(!/^[a-zçéäëïöü'’‘–—-]{3,20}$/i.test(value))
			throw new Error(`Invalid last name`);

		this._lastName = value;
	}

	get lastName() {
		return this._lastName;
	}

	set age(value) {
		if(value instanceof Number === false && typeof value !== "number")
			throw new TypeError(`No instance for ‘${Object(value).constructor.name}’ arising from a use of ‘age’`);

		if(value < 0 || value > 150)
			throw new RangeError(`Invalid age`);

		this._age = value;
	}

	get age() {
		return this._age;
	}
}


Вариант №2
class Person {
	constructor(firstName, lastName, age) {
		function validateName(type, name) {
			if(name instanceof String === false && typeof name !== "string")
				throw new TypeError(`No instance for ‘${Object(name).constructor.name}’ arising from a use of ‘${type}’`);

			if(name.length < 3 || name.length > 20)
				throw new RangeError(`Invalid length of ‘${type}’`);

			if(!/^[a-zçéäëïöü'’‘–—-]{3,20}$/i.test(name))
				throw new Error(`Invalid name of ‘${type}’`);
		}

		// names validation
		validateName("firstName", firstName);
		validateName("lastName", lastName);

		// age validation
		if(age instanceof Number === false && typeof age !== "number")
			throw new TypeError(`No instance for ‘${Object(age).constructor.name}’ arising from a use of ‘age’`);

		if(age < 0 || age > 150)
			throw new RangeError(`Invalid age`);

		this.firstName = firstName;
		this.lastName = lastName;
		this.age = age;

		Object.freeze(this);
	}
}


UPD Если вы хотите использовать синтаксис функции для объявления класса, то не забудьте проверить, чтобы this был инициализирован соответствующим образом! Поскольку если вы вызовете Person как функцию, то this указывает на глобальный объект/на другой this, если вызов в контексте и т. д. Вариант №3, похожий на ваш
function Person(firstName, lastName, age) {
	if(!new.target)
		throw new TypeError("Constructor ‘Person’ requires ‘new’");

	// проверки аргументов, например, как в примерах выше

	this.firstName = firstName;
	this.lastName = lastName;
	this.age = age;
	
	Object.freeze(this);
}

рони 21.05.2019 15:51

Цитата:

Сообщение от Malleys
if(value instanceof String === false && typeof value !== "string")

почему недостаточно typeof ?

Malleys 21.05.2019 16:07

Цитата:

Сообщение от рони
почему недостаточно typeof ?

А если представитель наследует от String? А если new String("name")?

Alexandroppolus 21.05.2019 16:08

Цитата:

Сообщение от рони
почему недостаточно typeof ?

На случай, если прилетит объектная обертка, для которой typeof будет 'object'
Цитата:

Сообщение от Malleys
if(!new.target)

Пока что мало поддерживается браузерами. А там где это есть, можно и class использовать без всяких бабелей.

Malleys 21.05.2019 16:32

Цитата:

Сообщение от Alexandroppolus
На случай, если прилетит объектная обертка, для которой typeof будет 'object'

На самом деле на случай, когда будет передана примитивная строка.

На самом же деле можно всё проще сделать: например, возраст можно рассматривать как тип Age, который является подмножеством Number. Тоже самое с именем, тип Name является подмножеством типа String. Т. е. не каждое число является возрастом, но любой возраст является числом!

Вот, наверное, самый лучший вариант...
class Age extends Number {
	constructor(age) {
		super(age);

		if(super.constructor.isNaN(this) || this < 0 || this > 150)
			throw new TypeError("Invalid age");
	}
}

class Name extends String {
	constructor(name) {
		super(name);

		if(this.length < 3 || this.length > 20 || !/^[a-zçéäëïöü'’‘–—-]{3,20}$/i.test(this))
			throw new TypeError("Invalid name");
	}
}

class Person {
	constructor(firstName, lastName, age) {
		this.firstName = new Name(firstName);
		this.lastName  = new Name(lastName);
		this.age       = new Age(age);

		Object.freeze(this);
	}
}


Цитата:

Сообщение от Alexandroppolus
Пока что [new.target] мало поддерживается браузерами.

на самом деле поддерживается очень хорошо!

Alexandroppolus 21.05.2019 16:49

Цитата:

Сообщение от Malleys
Вот, наверное, самый лучший вариант...

Будут обертки вместо примитивных типов. Рано или поздно наткнемся на функцию, которая проверяет только typeof (без instanceof). Лучше всегда примитивы юзать.
Цитата:

Сообщение от Malleys
на самом деле поддерживается очень хорошо!

Действительно. Я эту страницу на русском смотрел, видимо, она устаревшая

laimas 21.05.2019 17:15

Цитата:

Сообщение от Malleys
this > 150

Всем бы столько жить. )


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