Javascript-форум (https://javascript.ru/forum/)
-   Общие вопросы Javascript (https://javascript.ru/forum/misc/)
-   -   Классы на прототипах! (https://javascript.ru/forum/misc/85418-klassy-na-prototipakh.html)

Ctemmm9999 10.08.2023 16:04

Классы на прототипах!
 
Есть такая задача!(На литкод решал)
var ArrayWrapper = function(nums) {
this.nums = nums;
};

ArrayWrapper.prototype.valueOf = function() {
return this.nums.reduce((sum, num) => sum + num, 0);
}

ArrayWrapper.prototype.toString = function() {
return `[${this.nums.join(',')}]`;
}

const obj1 = new ArrayWrapper([1,2]);
const obj2 = new ArrayWrapper([3,4]);

console.log(obj1 + obj2); // 10
console.log(String(obj1)); // "[1,2]"
console.log(String(obj2)); // "[3,4]"


Вопрос такой! никак не пойму! Почему методы не вызываются, а только экземпляр класса, и он автоматически вызывает метод, будь то приведение к строке или сложение экземпляров!(как он понимает какой метод вызывать) Причём если в консоль просто вывести экземпляр, то он никаких действий, будь то приведение к строке или сложение не делает!

А вот такая запись мне более понятна что откуда!
console.log(obj1.valueOf() + obj2.valueOf()); // 10
console.log(String(obj1.toString())); // "[1,2]"
console.log(String(obj2.toString())); // "[3,4]"

Подскажите пжл!

Aetae 10.08.2023 16:44

Это стандартные "зарезервированные" методы вызываемые при приведении типов: valueOf - к числу(точнее к примитиву), toString - к строке.

Они просто неявяно вызываются для любых не-числа\не-строки когда их пытаются использовать как строку\число.

Есть ещё toJSON - для JSON.stringify, Symbol.iterator для итератора и т.п.

рони 10.08.2023 16:44

Ctemmm9999,
Пожалуйста, отформатируйте свой код!

Для этого его можно заключить в специальные теги: js/css/html и т.п., например:
[html run]
... минимальный код страницы с вашей проблемой
[/html]

О том, как вставить в сообщение исполняемый javascript и html-код, а также о дополнительных возможностях форматирования - читайте http://javascript.ru/formatting.

voraa 10.08.2023 16:45

Так в спецификации установлено.
Если операнд оператора + (-, *,/... в общем там, где должно быть число) является объектом, то автоматически вызывается метод valueOf этого объекта (если он есть), который должен вернуть число.
Тоже самое, когда нужно из объекта получить строку, автоматически вызывается метод toString, который должен вернуть строку

Ctemmm9999 10.08.2023 16:59

Аааа. Теперь всё стало на свои места! Всем большое спасибо!

voraa 10.08.2023 17:16

Ну там немного все сложнее.
Сначала ищется метод [Symbol.toPrimitive], и если он установлен, то вызывается с параметром, указывающем, что надо получить (число или строку), а если его нет, то в зависимости от ситуации если надо получить число, сначала ищется valueOf потом toString (если valueOf нет), а если надо получить строку, то сначала ищется toString, а если нет, то valueOf

Т.е можно было записать так
var ArrayWrapper = function(nums) {
this.nums = nums;
};

ArrayWrapper.prototype[Symbol.toPrimitive] = function (hint) {
	if (hint==='default' || hint==='number') {
		return this.nums.reduce((sum, num) => sum + num, 0);
	}
	return `[${this.nums.join(',')}]`;
}

const obj1 = new ArrayWrapper([1,2]);
const obj2 = new ArrayWrapper([3,4]);

console.log(obj1 + obj2); // 10
console.log(String(obj1)); // "[1,2]"
console.log(String(obj2)); // "[3,4]"


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