Ob'ektdan primitivga konvertatsiya

...

Ob'ektdan primitivga konvertatsiya

JavaScript ob'ektlarga operatorlar bilan ishlashni sozlash imkoniyatini bermaydi. Masalan, Ruby yoki C++ kabi boshqa dasturlash tillarida maxsus ob'ekt metodlarini qo'shishimiz mumkin, lekin JavaScriptda bunday imkoniyat mavjud emas.

Agar biz ob'ektlarni qo'shsak, ayrsak yoki alert(obj) orqali chop etsak, ob'ektlar avtomatik ravishda primitiv qiymatlarga aylantiriladi, va keyin operatsiya ushbu primitiv qiymatlar ustida amalga oshiriladi.

Bu juda muhim cheklov: obj1 + obj2 (yoki boshqa matematik operatsiyalar) natija sifatida ob'ektni qaytara olmaydi!

Masalan, biz vektorlar yoki matritsalarni ifodalovchi ob'ektlarni qo'shib, "qo'shilgan" ob'ektni olishimiz mumkin emas. Bunday arxitektura imkoniyatlari avtomatik ravishda "taxtadan chiqariladi".

Shuning uchun, amalda ob'ektlar bilan matematik operatsiyalar mavjud emas. Bunday holatlar juda kam uchraydi va odatda kod xatoliklaridan kelib chiqadi.

Bu bo'limda ob'ekt qanday qilib primitivga aylantirilishini va bu konvertatsiyani qanday sozlash mumkinligini ko'rib chiqamiz.

Konvertatsiya qoidalari

Avvalroq "Turlarni konvertatsiya qilish" bo'limida primitivlarning sonli, string va boolean konvertatsiya qoidalarini ko'rib chiqdik. Endi ob'ektlar uchun bu qoidalarni to'ldiramiz.

  • Boolean konvertatsiya mavjud emas. Barcha ob'ektlar boolean kontekstida true bo'ladi. Shunchaki, faqat sonli va string konvertatsiyalar mavjud.
  • Sonli konvertatsiya ob'ektlarni ayirish yoki matematik funksiyalarni qo'llashda amalga oshiriladi. Masalan, Date ob'ektlari (keyingi bo'limda ko'rib chiqamiz) ayirilishi mumkin va date1 - date2 natijasi ikki sana orasidagi vaqt farqini beradi.
  • String konvertatsiya odatda ob'ektni alert(obj) orqali chiqarishda yoki shunga o'xshash kontekstlarda amalga oshiriladi.

Konvertatsiya uchun qoidalar

JavaScript qanday konvertatsiya qo'llashni qanday aniqlaydi?

Boshqa dasturlash tillarida qo'llaniladigan uchta variant mavjud. Ular "hints" deb ataladi va spetsifikatsiyada quyidagicha tasvirlangan:

  • "string": ob'ektdan string konvertatsiya qilish uchun, masalan, alert kabi operatsiyalarda:

    // chiqarish
    alert(obj);
     
    // ob'ektni property kaliti sifatida ishlatish
    anotherObj[obj] = 123;
  • "number": ob'ektdan sonli konvertatsiya qilish uchun, masalan, matematik amallarda:

    // aniq konvertatsiya
    let num = Number(obj);
     
    // matematik (ikkilamchi qo'shishdan tashqari)
    let n = +obj; // unarni qo'shish
    let delta = date1 - date2;
     
    // kichikroq/yirikroq solishtirish
    let greater = user1 > user2;

    Ko'pgina o'rnatilgan matematik funksiyalar ham bunday konvertatsiyani o'z ichiga oladi.

  • "default": juda kam holatlarda operator "qanday turga umid qilmasligini" aniqlamaganida qo'llaniladi.

    Misol uchun, ikkilamchi qo'shish + ham stringlarni birlashtiradi, ham sonlarni qo'shadi. Agar ikkilamchi qo'shish ob'ektdan argument sifatida olinsa, u "default" hintini qo'llaydi va konvertatsiyani amalga oshiradi.

    Shuningdek, agar ob'ekt == orqali string, son yoki symbol bilan solishtirilsa, qaysi konvertatsiya amalga oshirilishi aniq bo'lmaydi, shuning uchun "default" hinti ishlatiladi.

    // ikkilamchi qo'shish "default" hintini ishlatadi
    let total = obj1 + obj2;
     
    // obj == number "default" hintini ishlatadi
    if (user == 1) { ... };

Symbol.toPrimitive

JavaScript quyidagi uchta ob'ekt metodlarini chaqiradi:

  1. obj[Symbol.toPrimitive](hint) - agar bunday metod mavjud bo'lsa, Symbol.toPrimitive yordamida chaqiriladi.
  2. Agar hint "string" bo'lsa:
    • obj.toString() yoki obj.valueOf() chaqiriladi, qaysi biri mavjud bo'lsa.
  3. Agar hint "number" yoki "default" bo'lsa:
    • obj.valueOf() yoki obj.toString() chaqiriladi, qaysi biri mavjud bo'lsa.

Symbol.toPrimitive - o'zgarish metodini belgilash uchun o'rnatilgan symbol:

obj[Symbol.toPrimitive] = function (hint) {
  // ob'ektdan primitivga konvertatsiya qilish kodi
  // hint = "string", "number", "default"dan biri
};

Agar Symbol.toPrimitive metodi mavjud bo'lsa, u barcha hintlar uchun ishlatiladi va boshqa metodlar kerak bo'lmaydi.

Masalan, user ob'ekti quyidagicha amalga oshiriladi:

let user = {
  name: 'John',
  money: 1000,
 
  [Symbol.toPrimitive](hint) {
    alert(`hint: ${hint}`);
    return hint == 'string' ? `{name: "${this.name}"}` : this.money;
  },
};
 
// konvertatsiya demo:
alert(user); // hint: string -> {name: "John"}
alert(+user); // hint: number -> 1000
alert(user + 500); // hint: default -> 1500

Bu kodda user ob'ekti string yoki number konvertatsiyasi uchun qanday ishlashini ko'rsating. Yagona metod user[Symbol.toPrimitive] barcha konvertatsiya holatlarini boshqaradi.

toString/valueOf

Agar Symbol.toPrimitive mavjud bo'lmasa, JavaScript toString va valueOf metodlarini izlaydi:

  • "string" hint uchun: toString metodi chaqiriladi, agar mavjud bo'lmasa yoki primitiv qiymat qaytarmasa, valueOf chaqiriladi (shuning uchun toString string konvertatsiyalar uchun ustunlikka ega).
  • Boshqa hintlar uchun: valueOf chaqiriladi, agar mavjud bo'lmasa yoki primitiv qiymat qaytarmasa, toString chaqiriladi (shuning uchun valueOf matematik konvertatsiyalar uchun ustunlikka ega).

Bu metodlar primitiv qiymat qaytarishi kerak. Agar toString yoki valueOf ob'ekt qaytarsa, u e'tiborga olinmaydi.

Misol:

let user = { name: 'John' };
 
alert(user); // [object Object]
alert(user.valueOf() === user); // true

Agar ob'ektni string sifatida ishlatsak, masalan, alert yoki shunga o'xshash, biz defaultda [object Object] ko'rishimiz mumkin.

Agar toString mavjud bo'lsa, konvertatsiya qilish uchun, valueOf metodini amalga oshirib, avvalgi kodni qayta ishlash mumkin.

Qo'shimcha konvertatsiyalar

Ko'pgina operatorlar va funksiyalar turlarni konvertatsiya qiladi, masalan, ko'paytirish * operandlarni sonlarga aylantiradi.

Agar ob'ekt argument sifatida o'tkazilsa, ikki bosqichli hisob-kitoblar mavjud:

  1. Ob'ekt primitivga aylantiriladi (yuqoridagi qoidalar bo'yicha).
  2. Agar zarur bo'lsa, natijaviy primitiv ham konvertatsiya qilinadi.

Misol:

let obj = {
  // toString barcha konvertatsiyalarni boshqaradi
  toString() {
    return '2';
  },
};
 
alert(obj * 2); // 4, ob'ekt primitivga "2" ga aylantiriladi, keyin ko'paytirish sonlarni o'zgaradi

Agar ob'ekt * bilan ko'paytirilsa, avval ob'ekt primitivga (string "2") aylantiriladi. Keyin "2" * 2 2 * 2 ga o'zgaradi (string songa kon

vertatsiya qilinadi).

Ikki marta qo'shish, stringlarni birlashtiradi:

let obj = {
  toString() {
    return '2';
  },
};
 
alert(obj + 2); // "22" ("2" + 2), konvertatsiya primitivga string qaytaradi => birlashtirish

Xulosa

Ob'ektdan primitivga konvertatsiya ko'plab o'rnatilgan funksiyalar va operatorlar tomonidan avtomatik ravishda amalga oshiriladi.

Uchta turdagi konvertatsiya mavjud:

  • "string" (string kerak bo'lgan operatsiyalar uchun)
  • "number" (matematik operatsiyalar uchun)
  • "default" (ba'zi operatorlar, odatda ob'ektlar "number" kabi ishlaydi)

Konvertatsiya algoritmi:

  1. Agar mavjud bo'lsa, obj[Symbol.toPrimitive](hint) chaqiriladi.
  2. Agar hint "string" bo'lsa:
    • obj.toString() yoki obj.valueOf() chaqiriladi, qaysi biri mavjud bo'lsa.
  3. Agar hint "number" yoki "default" bo'lsa:
    • obj.valueOf() yoki obj.toString() chaqiriladi, qaysi biri mavjud bo'lsa.

Barcha metodlar primitiv qiymat qaytarishi kerak (agar mavjud bo'lsa).

Amalda, ko'pincha obj.toString() faqat string konvertatsiyalar uchun “catch-all” metod sifatida ishlatiladi va ob'ektning “insonga o'xshash” ko'rinishini qaytaradi, loglash yoki debugging maqsadlari uchun.

Ushbu sahifada

GitHubda tahrirlash