برنامه نویسی

اضافه کردن شی به مسیر – تابع Util #3

Summarize this content to 400 words in Persian Lang
در روزهای گذشته چند ابزار JS را با شما به اشتراک گذاشتم تا اشیا را به طور مکرر حلقه کنید، و همچنین داده ها را در یک شی تودرتو دریافت کنید یا مسیر یک شی را به صورت برنامه ای تأیید کنید.

در ابزار امروزی، تابعی برای اضافه کردن یک شی دیگر در داخل یک شی در یک مسیر خاص دریافت خواهید کرد.

appendObj(parentObj, childObj, path, cloneParent = false, cloneChild = true)

/**
*
* @param {Object} parentObj the object itself
* @param {string[]} path the sequence to append
* @param {Object} dataTo the data you want to insert
* @returns {Object} the passed object with a the appended object
*/
function appendObj(parentObj, childObj, path, cloneParent = false, cloneChild = true) {
// Verify the parameters
if (getType(parentObj) != “object”) throw TypeError(“The `parentObj` argument is not an object”)
if (getType(childObj) != “object”) throw TypeError(“The `childObj` argument is not an object”)
if (getType(path) != “array”) throw TypeError(“The `path` argument is not an array”)
if (getType(cloneParent) != “boolean”) throw TypeError(“The `cloneParent` argument is not a boolean”)
if (getType(cloneChild) != “boolean”) throw TypeError(“The `cloneChild` argument is not a boolean”)

// clone the child object to avoid shallow copies
if (cloneChild) childObj = structuredClone(childObj)

// If the path is empty assign it at the root
if (path.length == 0) {
Object.assign(parentObj, childObj)
return parentObj;
}

// clone the parent object
if (cloneParent) parentObj = structuredClone(parentObj)

// Link a reference to the parent object
let objRef = parentObj;

// Create path and then assign the object
path.forEach((item, index) => {
if (!Object.keys(objRef).includes(item)) objRef[item] = {}
if (index < path.length – 1) {
objRef = objRef[item] } else {
if (getType(objRef[item]) != “object”) objRef[item] = {}
objRef = objRef[item] Object.assign(objRef, childObj);
}

});

// return the object
return parentObj;
}

/**
* A method to detect data types more accurately
* Credits: Chris Ferdinandi, https://gomakethings.com/
* @param {*} data the data to be verified
* @returns {String} the data type
*/
export function getType(data) {
return Object.prototype.toString.call(data).toLowerCase().slice(8, -1)
}

/**
* License: MIT, https://opensource.org/license/mit
* Copyright (c) 2024 Rodrigo Isaias Calix
*/

وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

چگونه از آن استفاده کنیم؟

تابع حداقل به 3 پارامتر و 2 پارامتر اختیاری به ترتیب زیر نیاز دارد:

parentObj: این شی اصلی است که می خواهید شی دیگری را در آن اضافه کنید

childObj: شیئی که می خواهید اضافه کنید

path: یک آرایه رشته ای که مسیر الحاق شی را نشان می دهد

cloneParent: یک بولی که نشان می دهد آیا شی والد شما باید شبیه سازی شود یا فقط به شما ارجاع داده شود، پیش فرض است false.

cloneChild: یک بولی که نشان می دهد که آیا شی فرزند باید شبیه سازی شود یا فقط به آن ارجاع داده شود، پیش فرض است true.

نمونه های استفاده:

با والد ارجاع شده (پیش فرض)

let products = {
externalDevices: {
keyboard: {
usb: 45,
bluetooth: 25,
}
}
}

const obj = {
mouses: {
usb: 60,
bluetooth: 80
}
}

appendObj(products, obj, [“externalDevices”]);

console.log(products)
/*
{
externalDevices: {
keyboard: {
usb: 45,
bluetooth: 25,
},
mouses: {
usb: 60,
bluetooth: 80
}
}
}
*/

وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

همانطور که می بینید، نیازی نیست چیزی را به متغیر اصلی شی اختصاص دهید، زیرا به طور پیش فرض تابع از شی اصلی به عنوان مرجع استفاده می کند و هر داده ای را به آن اضافه می کند.

با والد شبیه سازی شده

let copyObj = appendObj(products, obj, [“externalDevices”], true);

console.log(products)
/*
{
externalDevices: {
keyboard: {
usb: 45,
bluetooth: 25,
}
}
}
*/

console.log(copyObj)
/*
{
externalDevices: {
keyboard: {
usb: 45,
bluetooth: 25,
},
mouses: {
usb: 60,
bluetooth: 80
}
}
}
*/

وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

برخلاف مثال قبلی، این بار شی اصلی تغییر نمی کند زیرا شبیه سازی شده است. شما همچنین می توانید، استفاده کنید products متغیری که آن را به خود اختصاص دهد.

ایجاد یک مسیر شی خالی

appendObj(products, {}, [“externalDevices”, “mouses”, “bluetooth”]);
console.log(products);

/*
{
externalDevices: {
keyboard: {
usb: 45,
bluetooth: 25,
},
mouses: {
bluetooth: {}
}
}
}
*/

وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

نکاتی که باید قبل از استفاده از آن بدانید

چه زمانی cloneParent تنظیم شده است false شی والد فقط ارجاع داده می شود، این بدان معنی است که شما نیازی به تخصیص مجدد شیء به والد ندارید، به عبارت دیگر، اگر فقط خود تابع را اجرا کنید، به طور خودکار داده ها را به شی اصلی اضافه می کند. اگر تنظیم شده باشد true تابع یک کلون از شی والد را برمی گرداند، اما شی اصلی تحت تاثیر قرار نمی گیرد.
چه زمانی clonechildren تنظیم شده است true یک کلون از شی ایجاد می کند و آن را اضافه می کند. اما اگر آن را تنظیم کنید false یک کپی کم عمق از آن قرار می دهد، به این معنی که اگر شی اصلی دارای متغیرهایی در آن باشد و متغیرها تغییر کنند، هر مرجعی می تواند آن تغییر را نیز منعکس کند، با احتیاط استفاده کنید.
اگر تنظیم کنید path به یک آرایه خالی ([]) شی را به ریشه شی والد اختصاص می دهد
اگر مسیر شی تعریف نشده باشد، به طور خودکار ایجاد می شود. به عنوان مثال، اگر در products شی products.devices.audio.microphones “دستگاه” وجود ندارد، مسیر تا “میکروفون” را ایجاد می کند.
در مقصد مسیر، اگر مقصد یک شی باشد، شی فرزند در داخل آن شیء به همراه هر داده دیگری که دارد تخصیص داده می شود، این بدان معنی است که هر ویژگی شی یکسانی را که در آن قرار دارد، لغو می کند. اگر مقصد یک شی نباشد، کل مقدار را لغو می کند.

اگر این را مفید دیدید، من محتوای بیشتری مانند این را در DEV به اشتراک خواهم گذاشت!

شما همچنین می توانید من را در X: https://x.com/schemetastic

و به یاد داشته باشید که آن را برای بعد ذخیره کنید 🔖

در روزهای گذشته چند ابزار JS را با شما به اشتراک گذاشتم تا اشیا را به طور مکرر حلقه کنید، و همچنین داده ها را در یک شی تودرتو دریافت کنید یا مسیر یک شی را به صورت برنامه ای تأیید کنید.

در ابزار امروزی، تابعی برای اضافه کردن یک شی دیگر در داخل یک شی در یک مسیر خاص دریافت خواهید کرد.

appendObj(parentObj, childObj, path, cloneParent = false, cloneChild = true)

/**
 * 
 * @param {Object} parentObj the object itself
 * @param {string[]} path the sequence to append
 * @param {Object} dataTo the data you want to insert
 * @returns {Object} the passed object with a the appended object
 */
function appendObj(parentObj, childObj, path, cloneParent = false, cloneChild = true) {
    // Verify the parameters
    if (getType(parentObj) != "object") throw TypeError("The `parentObj` argument is not an object")
    if (getType(childObj) != "object") throw TypeError("The `childObj` argument is not an object")
    if (getType(path) != "array") throw TypeError("The `path` argument is not an array")
    if (getType(cloneParent) != "boolean") throw TypeError("The `cloneParent` argument is not a boolean")
    if (getType(cloneChild) != "boolean") throw TypeError("The `cloneChild` argument is not a boolean")

    // clone the child object to avoid shallow copies
    if (cloneChild) childObj = structuredClone(childObj)

    // If the path is empty assign it at the root
    if (path.length == 0) {
        Object.assign(parentObj, childObj)
        return parentObj;
    }

    // clone the parent object
    if (cloneParent) parentObj = structuredClone(parentObj)

    // Link a reference to the parent object
    let objRef = parentObj;

    // Create path and then assign the object
    path.forEach((item, index) => {
        if (!Object.keys(objRef).includes(item)) objRef[item] = {}
        if (index < path.length - 1) {
            objRef = objRef[item]
        } else {
            if (getType(objRef[item]) != "object") objRef[item] = {}
            objRef = objRef[item]
            Object.assign(objRef, childObj);
        }

    });

    // return the object
    return parentObj;
}

/**
 * A method to detect data types more accurately
 * Credits: Chris Ferdinandi, https://gomakethings.com/
 * @param {*} data the data to be verified
 * @returns {String} the data type
 */
export function getType(data) {
  return Object.prototype.toString.call(data).toLowerCase().slice(8, -1)
}

/**
 * License: MIT, https://opensource.org/license/mit
 * Copyright (c) 2024 Rodrigo Isaias Calix
 */

وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

چگونه از آن استفاده کنیم؟

تابع حداقل به 3 پارامتر و 2 پارامتر اختیاری به ترتیب زیر نیاز دارد:

  • parentObj: این شی اصلی است که می خواهید شی دیگری را در آن اضافه کنید
  • childObj: شیئی که می خواهید اضافه کنید
  • path: یک آرایه رشته ای که مسیر الحاق شی را نشان می دهد
  • cloneParent: یک بولی که نشان می دهد آیا شی والد شما باید شبیه سازی شود یا فقط به شما ارجاع داده شود، پیش فرض است false.
  • cloneChild: یک بولی که نشان می دهد که آیا شی فرزند باید شبیه سازی شود یا فقط به آن ارجاع داده شود، پیش فرض است true.

نمونه های استفاده:

با والد ارجاع شده (پیش فرض)

let products = {
    externalDevices: {
        keyboard: {
            usb: 45,
            bluetooth: 25,
        }
    }
}

const obj = {
    mouses: {
        usb: 60,
        bluetooth: 80
    }
}

appendObj(products, obj, ["externalDevices"]);

console.log(products)
/*
{
    externalDevices: {
        keyboard: {
            usb: 45,
            bluetooth: 25,
        },
        mouses: {
            usb: 60,
            bluetooth: 80
        }
    }
}
*/

وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

همانطور که می بینید، نیازی نیست چیزی را به متغیر اصلی شی اختصاص دهید، زیرا به طور پیش فرض تابع از شی اصلی به عنوان مرجع استفاده می کند و هر داده ای را به آن اضافه می کند.

با والد شبیه سازی شده

let copyObj = appendObj(products, obj, ["externalDevices"], true);

console.log(products)
/*
{
    externalDevices: {
        keyboard: {
            usb: 45,
            bluetooth: 25,
        }
    }
}
*/

console.log(copyObj)
/*
{
    externalDevices: {
        keyboard: {
            usb: 45,
            bluetooth: 25,
        },
        mouses: {
            usb: 60,
            bluetooth: 80
        }
    }
}
*/
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

برخلاف مثال قبلی، این بار شی اصلی تغییر نمی کند زیرا شبیه سازی شده است. شما همچنین می توانید، استفاده کنید products متغیری که آن را به خود اختصاص دهد.

ایجاد یک مسیر شی خالی

appendObj(products, {}, ["externalDevices", "mouses", "bluetooth"]);
console.log(products);

/*
{
    externalDevices: {
        keyboard: {
            usb: 45,
            bluetooth: 25,
        },
        mouses: {
            bluetooth: {}
        }
    }
}
*/

وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

نکاتی که باید قبل از استفاده از آن بدانید

  • چه زمانی cloneParent تنظیم شده است false شی والد فقط ارجاع داده می شود، این بدان معنی است که شما نیازی به تخصیص مجدد شیء به والد ندارید، به عبارت دیگر، اگر فقط خود تابع را اجرا کنید، به طور خودکار داده ها را به شی اصلی اضافه می کند. اگر تنظیم شده باشد true تابع یک کلون از شی والد را برمی گرداند، اما شی اصلی تحت تاثیر قرار نمی گیرد.
  • چه زمانی clonechildren تنظیم شده است true یک کلون از شی ایجاد می کند و آن را اضافه می کند. اما اگر آن را تنظیم کنید false یک کپی کم عمق از آن قرار می دهد، به این معنی که اگر شی اصلی دارای متغیرهایی در آن باشد و متغیرها تغییر کنند، هر مرجعی می تواند آن تغییر را نیز منعکس کند، با احتیاط استفاده کنید.
  • اگر تنظیم کنید path به یک آرایه خالی ([]) شی را به ریشه شی والد اختصاص می دهد
  • اگر مسیر شی تعریف نشده باشد، به طور خودکار ایجاد می شود. به عنوان مثال، اگر در products شی products.devices.audio.microphones “دستگاه” وجود ندارد، مسیر تا “میکروفون” را ایجاد می کند.
  • در مقصد مسیر، اگر مقصد یک شی باشد، شی فرزند در داخل آن شیء به همراه هر داده دیگری که دارد تخصیص داده می شود، این بدان معنی است که هر ویژگی شی یکسانی را که در آن قرار دارد، لغو می کند. اگر مقصد یک شی نباشد، کل مقدار را لغو می کند.

اگر این را مفید دیدید، من محتوای بیشتری مانند این را در DEV به اشتراک خواهم گذاشت!

شما همچنین می توانید من را در X: https://x.com/schemetastic

و به یاد داشته باشید که آن را برای بعد ذخیره کنید 🔖

نوشته های مشابه

دیدگاهتان را بنویسید

نشانی ایمیل شما منتشر نخواهد شد. بخش‌های موردنیاز علامت‌گذاری شده‌اند *

دکمه بازگشت به بالا