ЧÑо пÑоизойдÑÑ, еÑли ÑложиÑÑ Ð´Ð²Ð° обÑекÑа obj1 + obj2, вÑÑеÑÑÑ Ð¾Ð´Ð¸Ð½ из дÑÑгого obj1 - obj2 или вÑвеÑÑи иÑ
на ÑкÑан, воÑполÑзовавÑиÑÑ alert(obj)?
JavaScript ÑовеÑÑенно не позволÑÐµÑ Ð½Ð°ÑÑÑаиваÑÑ, как опеÑаÑоÑÑ ÑабоÑаÑÑ Ñ Ð¾Ð±ÑекÑами. РоÑлиÑие Ð¾Ñ Ð½ÐµÐºÐ¾ÑоÑÑÑ Ð´ÑÑÐ³Ð¸Ñ ÑзÑков пÑогÑаммиÑованиÑ, ÑÐ°ÐºÐ¸Ñ ÐºÐ°Ðº Ruby или C++, Ð¼Ñ Ð½Ðµ можем ÑеализоваÑÑ ÑпеÑиалÑнÑй обÑекÑнÑй меÑод Ð´Ð»Ñ Ð¾Ð±ÑабоÑки ÑÐ»Ð¾Ð¶ÐµÐ½Ð¸Ñ (или дÑÑÐ³Ð¸Ñ Ð¾Ð¿ÐµÑаÑоÑов).
Ð ÑлÑÑае ÑÐ°ÐºÐ¸Ñ Ð¾Ð¿ÐµÑаÑий, обÑекÑÑ Ð°Ð²ÑомаÑиÑеÑки пÑеобÑазÑÑÑÑÑ Ð² пÑимиÑивÑ, заÑем вÑполнÑеÑÑÑ Ñама опеÑаÑÐ¸Ñ Ð½Ð°Ð´ ÑÑими пÑимиÑивами, и на вÑÑ Ð¾Ð´Ðµ Ð¼Ñ Ð¿Ð¾Ð»ÑÑим пÑимиÑивное знаÑение.
ÐÑо важное огÑаниÑение: ÑезÑлÑÑаÑом obj1 + obj2 (или дÑÑгой маÑемаÑиÑеÑкой опеÑаÑии) не Ð¼Ð¾Ð¶ÐµÑ Ð±ÑÑÑ Ð´ÑÑгой обÑекÑ!
РпÑимеÑÑ, Ð¼Ñ Ð½Ðµ можем ÑоздаваÑÑ Ð¾Ð±ÑекÑÑ, пÑедÑÑавлÑÑÑие векÑоÑÑ Ð¸Ð»Ð¸ маÑÑиÑÑ (или доÑÑÐ¸Ð¶ÐµÐ½Ð¸Ñ Ð¸Ð»Ð¸ Ð¼Ð¾Ð¶ÐµÑ ÐµÑÑ ÑÑо-Ñо), ÑкладÑваÑÑ Ð¸Ñ Ð¸ ожидаÑÑ Ð² каÑеÑÑве ÑезÑлÑÑаÑа «ÑÑммиÑованнÑй» обÑекÑ. Такие аÑÑ Ð¸ÑекÑÑÑнÑе Ñ Ð¾Ð´Ñ Ð°Ð²ÑомаÑиÑеÑки оказÑваÑÑÑÑ Â«Ð·Ð° боÑÑом».
ÐÑак, поÑколÑÐºÑ Ð¼Ñ ÑÐµÑ Ð½Ð¸ÑеÑки здеÑÑ Ð¼Ð°Ð»Ð¾ ÑÑо можем ÑделаÑÑ, в ÑеалÑнÑÑ Ð¿ÑоекÑÐ°Ñ Ð½ÐµÑ Ð¼Ð°ÑемаÑики Ñ Ð¾Ð±ÑекÑами. ÐÑли она вÑÑ Ð¶Ðµ пÑоиÑÑ Ð¾Ð´Ð¸Ñ, Ñо за Ñедким иÑклÑÑением, ÑÑо из-за оÑибок в коде.
Ð ÑÑой главе Ð¼Ñ ÑаÑÑмоÑÑим, как обÑÐµÐºÑ Ð¿ÑеобÑазÑеÑÑÑ Ð² пÑимиÑив и как ÑÑо можно наÑÑÑоиÑÑ.
У Ð½Ð°Ñ ÐµÑÑÑ Ð´Ð²Ðµ Ñели:
- ÐÑо Ð¿Ð¾Ð·Ð²Ð¾Ð»Ð¸Ñ Ð½Ð°Ð¼ понÑÑÑ, ÑÑо пÑоиÑÑ Ð¾Ð´Ð¸Ñ Ð² ÑлÑÑае оÑибок в коде, когда ÑÐ°ÐºÐ°Ñ Ð¾Ð¿ÐµÑаÑÐ¸Ñ Ð¿ÑоизоÑла ÑлÑÑайно.
- ÐÑÑÑ Ð¸ÑклÑÑениÑ, когда Ñакие опеÑаÑии Ð²Ð¾Ð·Ð¼Ð¾Ð¶Ð½Ñ Ð¸ вполне ÑмеÑÑнÑ. ÐапÑимеÑ, вÑÑиÑание или ÑÑавнение Ð´Ð°Ñ (
DateобÑекÑÑ). ÐÑ Ð²ÑÑÑеÑимÑÑ Ñ Ð½Ð¸Ð¼Ð¸ позже.
ÐÑавила пÑеобÑазованиÑ
Рглаве ÐÑеобÑазование Ñипов Ð¼Ñ ÑаÑÑмоÑÑели пÑавила Ð´Ð»Ñ ÑиÑловÑÑ , ÑÑÑоковÑÑ Ð¸ логиÑеÑÐºÐ¸Ñ Ð¿ÑеобÑазований пÑимиÑивов. Ðо Ð¼Ñ Ð¾ÑÑавили пÑобел Ð´Ð»Ñ Ð¾Ð±ÑекÑов. ТепеÑÑ, когда Ð¼Ñ Ñже знаем о меÑÐ¾Ð´Ð°Ñ Ð¸ ÑÐ¸Ð¼Ð²Ð¾Ð»Ð°Ñ , пÑиÑло вÑÐµÐ¼Ñ Ð·Ð°Ð¿Ð¾Ð»Ð½Ð¸ÑÑ ÑÑÐ¾Ñ Ð¿Ñобел.
- Ðе ÑÑÑеÑÑвÑÐµÑ Ð¿ÑеобÑÐ°Ð·Ð¾Ð²Ð°Ð½Ð¸Ñ Ðº логиÑеÑÐºÐ¾Ð¼Ñ Ð·Ð½Ð°ÑениÑ. РлогиÑеÑком конÑекÑÑе вÑе обÑекÑÑ ÑвлÑÑÑÑÑ
true, вÑÑ Ð¿ÑоÑÑо. СÑÑеÑÑвÑÐµÑ Ð»Ð¸ÑÑ Ð¸Ñ ÑиÑловое и ÑÑÑоковое пÑеобÑазование. - ЧиÑловое пÑеобÑазование пÑоиÑÑ
одиÑ, когда Ð¼Ñ Ð²ÑÑиÑаем обÑекÑÑ Ð¸Ð»Ð¸ пÑименÑем маÑемаÑиÑеÑкие ÑÑнкÑии. ÐапÑимеÑ, обÑекÑÑ
Date(коÑоÑÑе бÑдÑÑ ÑаÑÑмоÑÑÐµÐ½Ñ Ð² главе ÐаÑа и вÑемÑ) могÑÑ Ð±ÑÑÑ Ð²ÑÑÑенÑ, и ÑезÑлÑÑаÑомdate1 - date2бÑÐ´ÐµÑ ÑазниÑа во вÑемени Ð¼ÐµÐ¶Ð´Ñ Ð´Ð²ÑÐ¼Ñ Ð´Ð°Ñами. - ЧÑо каÑаеÑÑÑ Ð¿ÑеобÑазований к ÑÑÑоке â оно обÑÑно пÑоиÑÑ
одиÑ, когда Ð¼Ñ Ð²Ñводим на ÑкÑан обÑÐµÐºÑ Ð¿Ñи помоÑи
alert(obj)и в подобнÑÑ ÐºÐ¾Ð½ÑекÑÑÐ°Ñ .
ÐÑ Ð¼Ð¾Ð¶ÐµÐ¼ ÑеализоваÑÑ Ñвои пÑеобÑÐ°Ð·Ð¾Ð²Ð°Ð½Ð¸Ñ Ðº ÑÑÑокам и ÑиÑлам, иÑполÑзÑÑ ÑпеÑиалÑнÑе обÑекÑнÑе меÑодÑ.
ТепеÑÑ Ð´Ð°Ð²Ð°Ð¹Ñе ÑглÑбимÑÑ Ð² деÑали. ÐÑо единÑÑвеннÑй пÑÑÑ Ð´Ð»Ñ Ñого, ÑÑÐ¾Ð±Ñ ÑазобÑаÑÑÑÑ Ð² нÑанÑÐ°Ñ ÑÑой ÑемÑ.
ХинÑÑ
Ðак JavaScript ÑеÑаеÑ, какое пÑеобÑазование пÑимениÑÑ?
СÑÑеÑÑвÑÐµÑ ÑÑи ваÑианÑа пÑеобÑÐ°Ð·Ð¾Ð²Ð°Ð½Ð¸Ñ Ñипов, коÑоÑÑе пÑоиÑÑ Ð¾Ð´ÑÑ Ð² ÑазлиÑнÑÑ ÑиÑÑаÑиÑÑ . Ðни назÑваÑÑÑÑ Â«Ñ Ð¸Ð½Ñами», как опиÑано в ÑпеÑиÑикаÑии:
"string"-
ÐÐ»Ñ Ð¿ÑеобÑÐ°Ð·Ð¾Ð²Ð°Ð½Ð¸Ñ Ð¾Ð±ÑекÑа к ÑÑÑоке, когда Ð¼Ñ Ð²ÑполнÑем опеÑаÑÐ¸Ñ Ð½Ð°Ð´ обÑекÑом, коÑоÑÐ°Ñ Ð¾Ð¶Ð¸Ð´Ð°ÐµÑ ÑÑÑокÑ, напÑимеÑ
alert:// вÑвод alert(obj); // иÑполÑзÑем обÑÐµÐºÑ Ð² каÑеÑÑве клÑÑа anotherObj[obj] = 123; "number"-
ÐÐ»Ñ Ð¿ÑеобÑÐ°Ð·Ð¾Ð²Ð°Ð½Ð¸Ñ Ð¾Ð±ÑекÑа к ÑиÑлÑ, в ÑлÑÑае маÑемаÑиÑеÑÐºÐ¸Ñ Ð¾Ð¿ÐµÑаÑий:
// Ñвное пÑеобÑазование let num = Number(obj); // маÑемаÑиÑеÑкие (не ÑÑиÑÐ°Ñ Ð±Ð¸Ð½Ð°Ñного плÑÑа) let n = +obj; // ÑнаÑнÑй плÑÑ let delta = date1 - date2; // ÑÑÐ°Ð²Ð½ÐµÐ½Ð¸Ñ Ð±Ð¾Ð»ÑÑе/менÑÑе let greater = user1 > user2;ÐолÑÑинÑÑво вÑÑÑоеннÑÑ Ð¼Ð°ÑемаÑиÑеÑÐºÐ¸Ñ ÑÑнкÑий Ñакже вклÑÑаÑÑ Ð² ÑÐµÐ±Ñ Ñакое пÑеобÑазование.
"default"-
ÐÑоиÑÑ Ð¾Ð´Ð¸Ñ Ñедко, когда опеÑаÑÐ¾Ñ Â«Ð½Ðµ ÑвеÑен», какой Ñип ожидаÑÑ.
ÐапÑимеÑ, бинаÑнÑй плÑÑ
+Ð¼Ð¾Ð¶ÐµÑ ÑабоÑаÑÑ ÐºÐ°Ðº Ñо ÑÑÑоками (обÑединÑÑ Ð¸Ñ Ð² однÑ), Ñак и Ñ ÑиÑлами (ÑкладÑÐ²Ð°Ñ Ð¸Ñ ). ÐоÑÑомÑ, еÑли бинаÑнÑй плÑÑ Ð¿Ð¾Ð»ÑÑÐ°ÐµÑ Ð¾Ð±ÑÐµÐºÑ Ð² каÑеÑÑве аÑгÑменÑа, он иÑполÑзÑÐµÑ Ñ Ð¸Ð½Ñ"default"Ð´Ð»Ñ ÐµÐ³Ð¾ пÑеобÑазованиÑ.Также, еÑли обÑÐµÐºÑ ÑÑавниваеÑÑÑ Ñ Ð¿Ð¾Ð¼Ð¾ÑÑÑ
==Ñо ÑÑÑокой, ÑиÑлом или Ñимволом, Ñоже неÑÑно, какое пÑеобÑазование ÑледÑÐµÑ Ð²ÑполниÑÑ, поÑÑÐ¾Ð¼Ñ Ð¸ÑполÑзÑеÑÑÑ Ñ Ð¸Ð½Ñ"default".// бинаÑнÑй плÑÑ Ð¸ÑполÑзÑÐµÑ Ñ Ð¸Ð½Ñ "default" let total = obj1 + obj2; // obj == number иÑполÑзÑÐµÑ Ñ Ð¸Ð½Ñ "default" if (user == 1) { ... };ÐпеÑаÑоÑÑ ÑÑÐ°Ð²Ð½ÐµÐ½Ð¸Ñ Ð±Ð¾Ð»ÑÑе/менÑÑе, Ñакие как
<>, Ñакже могÑÑ ÑабоÑаÑÑ ÐºÐ°Ðº Ñо ÑÑÑоками, Ñак и Ñ ÑиÑлами. Тем не менее, по иÑÑоÑиÑеÑким пÑиÑинам, они иÑполÑзÑÑÑ Ñ Ð¸Ð½Ñ"number", а не"default".
ÐпÑоÑем на пÑакÑике, вÑÑ Ð½ÐµÐ¼Ð½Ð¾Ð³Ð¾ пÑоÑе.
ÐÑе вÑÑÑоеннÑе обÑекÑÑ, за иÑклÑÑением одного (обÑÐµÐºÑ Date, коÑоÑÑй Ð¼Ñ ÑаÑÑмоÑÑим позже), ÑеализÑÑÑ "default" пÑеобÑазование Ñем же ÑпоÑобом, ÑÑо и "number". Рнам ÑледÑÐµÑ Ð¿Ð¾ÑÑÑпаÑÑ Ñак же.
ЧÑÐ¾Ð±Ñ Ð²ÑполниÑÑ Ð¿ÑеобÑазование, JavaScript пÑÑаеÑÑÑ Ð½Ð°Ð¹Ñи и вÑзваÑÑ ÑÑи ÑледÑÑÑÐ¸Ñ Ð¼ÐµÑода обÑекÑа:
- ÐÑзваÑÑ
obj[Symbol.toPrimitive](hint)â меÑод Ñ ÑимволÑнÑм клÑÑомSymbol.toPrimitive(ÑиÑÑемнÑй Ñимвол), еÑли Ñакой меÑод ÑÑÑеÑÑвÑеÑ, - ÐнаÑе, еÑли Ñ
Ð¸Ð½Ñ Ñавен
"string"- попÑобоваÑÑ Ð²ÑзваÑÑ
obj.toString()илиobj.valueOf(), ÑмоÑÑÑ ÐºÐ°ÐºÐ¾Ð¹ из Ð½Ð¸Ñ ÑÑÑеÑÑвÑеÑ.
- попÑобоваÑÑ Ð²ÑзваÑÑ
- ÐнаÑе, еÑли Ñ
Ð¸Ð½Ñ Ñавен
"number"или"default"- попÑобоваÑÑ Ð²ÑзваÑÑ
obj.valueOf()илиobj.toString(), ÑмоÑÑÑ ÐºÐ°ÐºÐ¾Ð¹ из Ð½Ð¸Ñ ÑÑÑеÑÑвÑеÑ.
- попÑобоваÑÑ Ð²ÑзваÑÑ
Symbol.toPrimitive
ÐавайÑе наÑнÑм Ñ Ð¿ÐµÑвого меÑода. ÐÑÑÑ Ð²ÑÑÑоеннÑй Ñимвол Ñ Ð¸Ð¼ÐµÐ½ÐµÐ¼ Symbol.toPrimitive, коÑоÑÑй ÑледÑÐµÑ Ð¸ÑполÑзоваÑÑ Ð´Ð»Ñ Ð¾Ð±Ð¾Ð·Ð½Ð°ÑÐµÐ½Ð¸Ñ Ð¼ÐµÑода пÑеобÑазованиÑ, Ð²Ð¾Ñ Ñак:
obj[Symbol.toPrimitive] = function(hint) {
// Ð²Ð¾Ñ ÐºÐ¾Ð´ Ð´Ð»Ñ Ð¿ÑеобÑÐ°Ð·Ð¾Ð²Ð°Ð½Ð¸Ñ ÑÑого обÑекÑа в пÑимиÑив
// он должен веÑнÑÑÑ Ð¿ÑимиÑивное знаÑение
// hint = ÑемÑ-Ñо из "string", "number", "default"
};
ÐÑли меÑод Symbol.toPrimitive ÑÑÑеÑÑвÑеÑ, он иÑполÑзÑеÑÑÑ Ð´Ð»Ñ Ð²ÑеÑ
Ñ
инÑов, и болÑÑе никакиÑ
меÑодов не ÑÑебÑеÑÑÑ.
ÐапÑимеÑ, здеÑÑ Ð¾Ð±ÑÐµÐºÑ user ÑеализÑÐµÑ ÐµÐ³Ð¾:
let user = {
name: "John",
money: 1000,
[Symbol.toPrimitive](hint) {
alert(`hint: ${hint}`);
return hint == "string" ? `{name: "${this.name}"}` : this.money;
}
};
// демонÑÑÑаÑÐ¸Ñ ÑезÑлÑÑаÑов пÑеобÑазований:
alert(user); // hint: string -> {name: "John"}
alert(+user); // hint: number -> 1000
alert(user + 500); // hint: default -> 1500
Ðак Ð¼Ñ Ð¼Ð¾Ð¶ÐµÐ¼ видеÑÑ Ð¸Ð· кода, user ÑÑановиÑÑÑ Ð»Ð¸Ð±Ð¾ ÑÑÑокой Ñо Ñвоим опиÑанием, либо ÑÑммой денег в завиÑимоÑÑи Ð¾Ñ Ð¿ÑеобÑазованиÑ. ÐдинÑй меÑод user[Symbol.toPrimitive] обÑабаÑÑÐ²Ð°ÐµÑ Ð²Ñе ÑлÑÑаи пÑеобÑазованиÑ.
toString/valueOf
ÐÑли Ð½ÐµÑ Symbol.toPrimitive, Ñогда JavaScript пÑÑаеÑÑÑ Ð½Ð°Ð¹Ñи меÑÐ¾Ð´Ñ toString и valueOf:
- ÐÐ»Ñ Ñ
инÑа
"string": вÑзваÑÑ Ð¼ÐµÑодtoString, а еÑли он не ÑÑÑеÑÑвÑÐµÑ Ð¸Ð»Ð¸ возвÑаÑÐ°ÐµÑ Ð¾Ð±ÑÐµÐºÑ Ð²Ð¼ÐµÑÑо пÑимиÑивного знаÑениÑ, ÑоvalueOf(Ñаким обÑазом,toStringÐ¸Ð¼ÐµÐµÑ Ð¿ÑиоÑиÑÐµÑ Ð¿Ñи ÑÑÑоковом пÑеобÑазовании). - ÐÐ»Ñ Ð´ÑÑгиÑ
Ñ
инÑов: вÑзваÑÑ Ð¼ÐµÑод
valueOf, а еÑли он не ÑÑÑеÑÑвÑÐµÑ Ð¸Ð»Ð¸ возвÑаÑÐ°ÐµÑ Ð¾Ð±ÑÐµÐºÑ Ð²Ð¼ÐµÑÑо пÑимиÑивного знаÑениÑ, ÑоtoString(Ñаким обÑазом,valueOfÐ¸Ð¼ÐµÐµÑ Ð¿ÑиоÑиÑÐµÑ Ð´Ð»Ñ Ð¼Ð°ÑемаÑиÑеÑÐºÐ¸Ñ Ð¾Ð¿ÐµÑаÑий).
ÐеÑÐ¾Ð´Ñ toString и valueOf беÑÑÑ ÑÐ²Ð¾Ñ Ð½Ð°Ñало Ñ Ð´ÑевниÑ
вÑемÑн. ÐÑо не ÑÐ¸Ð¼Ð²Ð¾Ð»Ñ (Ñимволов Ñогда еÑÑ Ð½Ðµ бÑло), а ÑкоÑее пÑоÑÑо «обÑÑнÑе» меÑÐ¾Ð´Ñ Ñо ÑÑÑоковÑми именами. Ðни пÑедоÑÑавлÑÑÑ Ð°Ð»ÑÑеÑнаÑивнÑй «ÑÑаÑомоднÑй» ÑпоÑоб ÑеализаÑии пÑеобÑазованиÑ.
ÐÑи меÑÐ¾Ð´Ñ Ð´Ð¾Ð»Ð¶Ð½Ñ Ð²Ð¾Ð·Ð²ÑаÑаÑÑ Ð¿ÑимиÑивное знаÑение. ÐÑли toString или valueOf возвÑаÑÐ°ÐµÑ Ð¾Ð±ÑекÑ, Ñо он игноÑиÑÑеÑÑÑ (Ñак же, как еÑли Ð±Ñ Ð¼ÐµÑода не бÑло).
Ðо ÑмолÑÐ°Ð½Ð¸Ñ Ð¾Ð±ÑÑнÑй обÑÐµÐºÑ Ð¸Ð¼ÐµÐµÑ ÑледÑÑÑие меÑÐ¾Ð´Ñ toString и valueOf:
- ÐеÑод
toStringвозвÑаÑÐ°ÐµÑ ÑÑÑокÑ"[object Object]". - ÐеÑод
valueOfвозвÑаÑÐ°ÐµÑ Ñам обÑекÑ.
ÐзглÑниÑе на пÑимеÑ:
let user = {name: "John"};
alert(user); // [object Object]
alert(user.valueOf() === user); // true
Таким обÑазом, еÑли Ð¼Ñ Ð¿Ð¾Ð¿ÑÑаемÑÑ Ð¸ÑполÑзоваÑÑ Ð¾Ð±ÑÐµÐºÑ Ð² каÑеÑÑве ÑÑÑоки, как напÑÐ¸Ð¼ÐµÑ Ð² alert или вÑоде Ñого, Ñо по ÑмолÑÐ°Ð½Ð¸Ñ Ð¼Ñ Ñвидим [object Object].
ÐнаÑение по ÑмолÑÐ°Ð½Ð¸Ñ valueOf ÑпоминаеÑÑÑ Ð·Ð´ÐµÑÑ ÑолÑко Ð´Ð»Ñ Ð¿Ð¾Ð»Ð½Ð¾ÑÑ ÐºÐ°ÑÑинÑ, ÑÑÐ¾Ð±Ñ Ð¸Ð·Ð±ÐµÐ¶Ð°ÑÑ ÐºÐ°ÐºÐ¾Ð¹-либо пÑÑаниÑÑ. Ðак Ð²Ñ Ð¼Ð¾Ð¶ÐµÑе видеÑÑ, он возвÑаÑÐ°ÐµÑ Ñам обÑÐµÐºÑ Ð¸ поÑÑÐ¾Ð¼Ñ Ð¸Ð³Ð½Ð¾ÑиÑÑеÑÑÑ. Ðе ÑпÑаÑивайÑе Ð¼ÐµÐ½Ñ Ð¿Ð¾ÑемÑ, ÑÑо по иÑÑоÑиÑеÑким пÑиÑинам. Так ÑÑо Ð¼Ñ Ð¼Ð¾Ð¶ÐµÐ¼ пÑедположиÑÑ, ÑÑо его не ÑÑÑеÑÑвÑеÑ.
ÐавайÑе пÑименим ÑÑи меÑÐ¾Ð´Ñ Ð´Ð»Ñ Ð½Ð°ÑÑÑойки пÑеобÑазованиÑ.
ÐÐ»Ñ Ð¿ÑимеÑа, иÑполÑзÑем иÑ
в ÑеализаÑии вÑÑ Ñого же обÑекÑа user. Ðо Ñже иÑполÑзÑÑ ÐºÐ¾Ð¼Ð±Ð¸Ð½Ð°ÑÐ¸Ñ toString и valueOf вмеÑÑо Symbol.toPrimitive:
let user = {
name: "John",
money: 1000,
// Ð´Ð»Ñ Ñ
инÑа Ñавного "string"
toString() {
return `{name: "${this.name}"}`;
},
// Ð´Ð»Ñ Ñ
инÑа Ñавного "number" или "default"
valueOf() {
return this.money;
}
};
alert(user); // toString -> {name: "John"}
alert(+user); // valueOf -> 1000
alert(user + 500); // valueOf -> 1500
Ðак видим, полÑÑилоÑÑ Ñо же поведение, ÑÑо и в пÑедÑдÑÑем пÑимеÑе Ñ Symbol.toPrimitive.
ÐоволÑно ÑаÑÑо нам нÑжно единое «ÑнивеÑÑалÑное» меÑÑо Ð´Ð»Ñ Ð¾Ð±ÑабоÑки вÑеÑ
пÑимиÑивнÑÑ
пÑеобÑазований. Ð ÑÑом ÑлÑÑае Ð¼Ñ Ð¼Ð¾Ð¶ÐµÐ¼ ÑеализоваÑÑ ÑолÑко toString:
let user = {
name: "John",
toString() {
return this.name;
}
};
alert(user); // toString -> John
alert(user + 500); // toString -> John500
РоÑÑÑÑÑÑвие Symbol.toPrimitive и valueOf, toString обÑабоÑÐ°ÐµÑ Ð²Ñе пÑимиÑивнÑе пÑеобÑазованиÑ.
ÐÑеобÑазование Ð¼Ð¾Ð¶ÐµÑ Ð²ÐµÑнÑÑÑ Ð»Ñбой пÑимиÑивнÑй Ñип
ÐÐ°Ð¶Ð½Ð°Ñ Ð²ÐµÑÑ, коÑоÑÑÑ ÑледÑÐµÑ Ð·Ð½Ð°ÑÑ Ð¾Ð±Ð¾ вÑÐµÑ Ð¼ÐµÑÐ¾Ð´Ð°Ñ Ð¿ÑеобÑÐ°Ð·Ð¾Ð²Ð°Ð½Ð¸Ñ Ð¿ÑимиÑивов, заклÑÑаеÑÑÑ Ð² Ñом, ÑÑо они не обÑзаÑелÑно возвÑаÑаÑÑ Ð¿Ð¾Ð´ÑказаннÑй Ñ Ð¸Ð½Ñом пÑимиÑив.
ÐÐµÑ Ð½Ð¸ÐºÐ°ÐºÐ¾Ð³Ð¾ конÑÑÐ¾Ð»Ñ Ð½Ð°Ð´ Ñем, веÑнÑÑ Ð»Ð¸ toString именно ÑÑÑокÑ, или ÑÑÐ¾Ð±Ñ Ð¼ÐµÑод Symbol.toPrimitive возвÑаÑал именно ÑиÑло Ð´Ð»Ñ Ñ
инÑа "number".
ÐдинÑÑвенное обÑзаÑелÑное ÑÑловие: ÑÑи меÑÐ¾Ð´Ñ Ð´Ð¾Ð»Ð¶Ð½Ñ Ð²Ð¾Ð·Ð²ÑаÑаÑÑ Ð¿ÑимиÑив, а не обÑекÑ.
Ðо иÑÑоÑиÑеÑким пÑиÑинам, еÑли toString или valueOf веÑнÑÑ Ð¾Ð±ÑекÑ, Ñо оÑибки не бÑдеÑ, но Ñакое знаÑение бÑÐ´ÐµÑ Ð¿ÑоигноÑиÑовано (как еÑли Ð±Ñ Ð¼ÐµÑода вообÑе не ÑÑÑеÑÑвовало). ÐÑо вÑÑ Ð¿Ð¾ÑомÑ, ÑÑо в дÑевние вÑемена в JavaScript не бÑло Ñ
оÑоÑей конÑепÑии «оÑибки».
Ð Ð²Ð¾Ñ Symbol.toPrimitive Ñже «ÑеÑÑе», ÑÑÐ¾Ñ Ð¼ÐµÑод обÑзан возвÑаÑаÑÑ Ð¿ÑимиÑив, инаÑе бÑÐ´ÐµÑ Ð¾Ñибка.
ÐалÑнейÑие пÑеобÑазованиÑ
Ðак Ð¼Ñ Ñже знаем, многие опеÑаÑоÑÑ Ð¸ ÑÑнкÑии вÑполнÑÑÑ Ð¿ÑеобÑÐ°Ð·Ð¾Ð²Ð°Ð½Ð¸Ñ Ñипов, напÑимеÑ, Ñмножение * пÑеобÑазÑÐµÑ Ð¾Ð¿ÐµÑÐ°Ð½Ð´Ñ Ð² ÑиÑла.
ÐÑли Ð¼Ñ Ð¿ÐµÑедаÑм обÑÐµÐºÑ Ð² каÑеÑÑве аÑгÑменÑа, Ñо в вÑÑиÑлениÑÑ Ð±ÑдÑÑ Ð´Ð²Ðµ ÑÑадии:
- ÐбÑÐµÐºÑ Ð¿ÑеобÑазÑеÑÑÑ Ð² пÑимиÑив (Ñ Ð¸ÑполÑзованием пÑавил, опиÑаннÑÑ Ð²ÑÑе).
- ÐÑли Ð½ÐµÐ¾Ð±Ñ Ð¾Ð´Ð¸Ð¼Ð¾ Ð´Ð»Ñ Ð´Ð°Ð»ÑнейÑÐ¸Ñ Ð²ÑÑиÑлений, ÑÑÐ¾Ñ Ð¿ÑимиÑив пÑеобÑазÑеÑÑÑ Ð´Ð°Ð»ÑÑе.
ÐапÑимеÑ:
let obj = {
// toString обÑабаÑÑÐ²Ð°ÐµÑ Ð²Ñе пÑеобÑÐ°Ð·Ð¾Ð²Ð°Ð½Ð¸Ñ Ð² ÑлÑÑае оÑÑÑÑÑÑÐ²Ð¸Ñ Ð´ÑÑгиÑ
меÑодов
toString() {
return "2";
}
};
alert(obj * 2); // 4, обÑÐµÐºÑ Ð±Ñл пÑеобÑазован к пÑимиÑÐ¸Ð²Ñ "2", заÑем Ñмножение Ñделало его ÑиÑлом
- Умножение
obj * 2ÑнаÑала пÑеобÑазÑÐµÑ Ð¾Ð±ÑÐµÐºÑ Ð² пÑимиÑив (ÑÑо ÑÑÑока"2"). - ÐаÑем
"2" * 2ÑÑановиÑÑÑ2 * 2(ÑÑÑока пÑеобÑазÑеÑÑÑ Ð² ÑиÑло).
РвоÑ, к пÑимеÑÑ, бинаÑнÑй плÑÑ Ð² подобной ÑиÑÑаÑии Ñоединил Ð±Ñ ÑÑÑоки, Ñак как он ÑовÑем не бÑезгÑÐµÑ ÑÑÑок:
let obj = {
toString() {
return "2";
}
};
alert(obj + 2); // "22" ("2" + 2), пÑеобÑазование к пÑимиÑÐ¸Ð²Ñ Ð²ÐµÑнÑло ÑÑÑÐ¾ÐºÑ => конкаÑенаÑиÑ
ÐÑого
ÐÑеобÑазование обÑекÑа в пÑимиÑив вÑзÑваеÑÑÑ Ð°Ð²ÑомаÑиÑеÑки многими вÑÑÑоеннÑми ÑÑнкÑиÑми и опеÑаÑоÑами, коÑоÑÑе ожидаÑÑ Ð¿ÑимиÑив в каÑеÑÑве знаÑениÑ.
СÑÑеÑÑвÑÐµÑ Ð²Ñего 3 Ñипа (Ñ Ð¸Ð½Ñа) Ð´Ð»Ñ ÑÑого:
"string"(длÑalertи дÑÑÐ³Ð¸Ñ Ð¾Ð¿ÐµÑаÑий, коÑоÑÑм нÑжна ÑÑÑока)"number"(Ð´Ð»Ñ Ð¼Ð°ÑемаÑиÑеÑÐºÐ¸Ñ Ð¾Ð¿ÐµÑаÑий)"default"(Ð´Ð»Ñ Ð½ÐµÐºÐ¾ÑоÑÑÑ Ð´ÑÑÐ³Ð¸Ñ Ð¾Ð¿ÐµÑаÑоÑов, обÑÑно обÑекÑÑ ÑеализÑÑÑ ÐµÐ³Ð¾ как"number")
СпеÑиÑикаÑÐ¸Ñ Ñвно опиÑÑÐ²Ð°ÐµÑ Ð´Ð»Ñ ÐºÐ°Ð¶Ð´Ð¾Ð³Ð¾ опеÑаÑоÑа, какой ÐµÐ¼Ñ ÑледÑÐµÑ Ð¸ÑполÑзоваÑÑ Ñ Ð¸Ð½Ñ.
ÐлгоÑиÑм пÑеобÑÐ°Ð·Ð¾Ð²Ð°Ð½Ð¸Ñ Ñаков:
- СнаÑала вÑзÑваеÑÑÑ Ð¼ÐµÑод
obj[Symbol.toPrimitive](hint), еÑли он ÑÑÑеÑÑвÑеÑ, - Ð ÑлÑÑае, еÑли Ñ
Ð¸Ð½Ñ Ñавен
"string"- пÑоиÑÑ
Ð¾Ð´Ð¸Ñ Ð¿Ð¾Ð¿ÑÑка вÑзваÑÑ
obj.toString()иobj.valueOf(), ÑмоÑÑÑ ÑÑо еÑÑÑ.
- пÑоиÑÑ
Ð¾Ð´Ð¸Ñ Ð¿Ð¾Ð¿ÑÑка вÑзваÑÑ
- Ð ÑлÑÑае, еÑли Ñ
Ð¸Ð½Ñ Ñавен
"number"или"default"- пÑоиÑÑ
Ð¾Ð´Ð¸Ñ Ð¿Ð¾Ð¿ÑÑка вÑзваÑÑ
obj.valueOf()иobj.toString(), ÑмоÑÑÑ ÑÑо еÑÑÑ.
- пÑоиÑÑ
Ð¾Ð´Ð¸Ñ Ð¿Ð¾Ð¿ÑÑка вÑзваÑÑ
ÐÑе ÑÑи меÑÐ¾Ð´Ñ Ð´Ð¾Ð»Ð¶Ð½Ñ Ð²Ð¾Ð·Ð²ÑаÑаÑÑ Ð¿ÑимиÑив (еÑли опÑеделенÑ).
Ðа пÑакÑике ÑаÑÑо бÑÐ²Ð°ÐµÑ Ð´Ð¾ÑÑаÑоÑно ÑеализоваÑÑ ÑолÑко obj.toString() в каÑеÑÑве ÑнивеÑÑалÑного меÑода Ð´Ð»Ñ Ð¿ÑеобÑазований к ÑÑÑоке, коÑоÑÑй должен возвÑаÑаÑÑ ÑдобоÑиÑаемое пÑедÑÑавление обÑекÑа Ð´Ð»Ñ Ñелей логиÑÐ¾Ð²Ð°Ð½Ð¸Ñ Ð¸Ð»Ð¸ оÑладки.
ÐомменÑаÑии
<code>, Ð´Ð»Ñ Ð½ÐµÑколÑÐºÐ¸Ñ ÑÑÑок кода — Ñег<pre>, еÑли болÑÑе 10 ÑÑÑок — ÑÑÑÐ»ÐºÑ Ð½Ð° пеÑоÑниÑÑ (plnkr, JSBin, codepenâ¦)