CINXE.COM

<!DOCTYPE html><html lang="es" data-theme-enabled="1"><head><script>window.currentUser = null;</script><script>window.shopCurrency = "EUR";</script><script>window.localCurrency = "EUR";</script><script>window.countryCode = "fi";</script><script>window.rateShopTo = {"EUR":1,"USD":1.0784426856242513,"AMD":422.9305849580972};</script><title itemprop="name">Referencias de objetos y copia</title><link href="/pack/styles.100020a0bc7cf13be729.css" rel="stylesheet"><meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=yes, minimum-scale=1.0"><meta name="apple-mobile-web-app-capable" content="yes"><!-- chrome autotranslate is enabled only for "en" main version--><meta name="google" content="notranslate"><script>if (window.devicePixelRatio > 1) document.cookie = 'pixelRatio=' + window.devicePixelRatio + ';path=/;expires=Tue, 19 Jan 2038 03:14:07 GMT';</script><link href="//fonts.googleapis.com/css?family=Open+Sans:bold,italic,bolditalic" rel="stylesheet"><link rel="apple-touch-icon-precomposed" href="/img/favicon/apple-touch-icon-precomposed.png"><link rel="canonical" href="https://es.javascript.info/object-copy"><meta name="msapplication-TileColor" content="#222A2C"><meta name="msapplication-TileImage" content="/img/favicon/tileicon.png"><link rel="icon" href="/img/favicon/favicon.png"><meta itemprop="image" content="https://es.javascript.info/img/site_preview_en_512x512.png"><meta property="og:title" content="Referencias de objetos y copia"><meta property="og:image" content="https://es.javascript.info/img/site_preview_en_1200x630.png"><meta property="og:image:type" content="image/png"><meta property="og:image:width" content="1200"><meta property="og:image:height" content="630"><meta property="fb:admins" content="100001562528165"><meta name="twitter:card" content="summary"><meta name="twitter:title" content="Referencias de objetos y copia"><meta name="twitter:site" content="@iliakan"><meta name="twitter:creator" content="@iliakan"><meta name="twitter:image" content="https://es.javascript.info/img/site_preview_en_512x512.png"><meta name="google-adsense-account" content="ca-pub-6204518652652613"><link rel="prev" href="/object"><link rel="next" href="/garbage-collection"><script data-collect-dnt="true" async src="https://scripts.simpleanalyticscdn.com/latest.js"></script><script>window.GA_ID = "UA-2056213-15";</script><script>window.YANDEX_METRIKA_ID = 32184394;</script><script>{function gtag(){dataLayer.push(arguments)}window.dataLayer=window.dataLayer||[],gtag("js",new Date),gtag("config","G-2LWB61WGYJ")}</script> <script async src="https://www.googletagmanager.com/gtag/js?id=G-2LWB61WGYJ"></script><script>window.metrika={reachGoal:function(){}},window.yandex_metrika_callbacks=[function(){try{window.metrika=new Ya.Metrika({id:YANDEX_METRIKA_ID,webvisor:!0,clickmap:!0,params:{user:window.currentUser&&window.currentUser.id}}),metrika.trackLinks({delay:150}),window.addEventListener("error",function(r){window.metrika.reachGoal("JSERROR",{src:(r.filename||r.errorUrl)+": "+(r.lineno||r.errorLine),stack:r.stack||r.error&&r.error.stack,message:r.message})})}catch(r){}}];</script><script src="//mc.yandex.ru/metrika/watch.js" async></script><script>window.RECAPTCHA_ID = "6LfmLAEVAAAAAJMykMnf7aY8nkyTRmYi2ynx51R1";</script><script src="/pack/init.bfbd8f163f7371f4e613.js"></script><script src="/pack/head.f0ef0d46af631501e6b2.js" defer></script><meta property="og:title" content="Referencias de objetos y copia"><meta property="og:type" content="article"><script src="/pack/tutorial.7c36b8184a7e0fd79e5d.js" defer></script><script src="/pack/footer.d61f12af96e4007b382f.js" defer></script></head><body class="no-icons"><script>window.fontTest();</script><div class="page-wrapper page-wrapper_sidebar_on"><!--[if IE]><div style="color:red;text-align:center">Lo sentimos, Internet Explorer no es compatible. Utilice un navegador más nuevo.</div><![endif]--><div class="sitetoolbar sitetoolbar_tutorial"><script>window.langs = [{"code":"ar","name":"Arabic"},{"code":"az","name":"Azerbaijani"},{"code":"bg","name":"Bulgarian"},{"code":"bn","name":"Bengali"},{"code":"bs","name":"Bosnian"},{"code":"ca","name":"Catalan"},{"code":"cs","name":"Czech"},{"code":"da","name":"Danish"},{"code":"de","name":"German"},{"code":"el","name":"Greek"},{"code":"en","name":"English"},{"code":"es","name":"Spanish"},{"code":"fa","name":"Persian (Farsi)"},{"code":"fi","name":"Finnish"},{"code":"fr","name":"French"},{"code":"he","name":"Hebrew"},{"code":"hi","name":"Hindi"},{"code":"hr","name":"Croatian"},{"code":"hu","name":"Hungarian"},{"code":"hy","name":"Armenian"},{"code":"id","name":"Indonesian"},{"code":"it","name":"Italian"},{"code":"ja","name":"Japanese"},{"code":"ka","name":"Georgian"},{"code":"kk","name":"Kazakh"},{"code":"km","name":"Central Khmer"},{"code":"ko","name":"Korean"},{"code":"ku","name":"Kurdish"},{"code":"ky","name":"Kyrgyz"},{"code":"lt","name":"Lithuanian"},{"code":"me","name":"Montenegrin"},{"code":"ml","name":"Malayalam"},{"code":"ms","name":"Malay"},{"code":"my","name":"Burmese"},{"code":"nl","name":"Dutch"},{"code":"no","name":"Norvegian"},{"code":"pa","name":"Punjabi"},{"code":"pl","name":"Polish"},{"code":"pt","name":"Portuguese"},{"code":"ro","name":"Romanian"},{"code":"ru","name":"Russian"},{"code":"si","name":"Sinhala"},{"code":"sk","name":"Slovak"},{"code":"sl","name":"Slovenian"},{"code":"sq","name":"Albanian"},{"code":"sr","name":"Serbian"},{"code":"ta","name":"Tamil"},{"code":"te","name":"Telugu"},{"code":"test","name":"Test"},{"code":"th","name":"Thai"},{"code":"tk","name":"Turkmen"},{"code":"tr","name":"Turkish"},{"code":"ug","name":"Uyghur"},{"code":"uk","name":"Ukrainian"},{"code":"ur","name":"Urdu"},{"code":"uz","name":"Uzbek"},{"code":"v2","name":"v2"},{"code":"vi","name":"Vietnamese"},{"code":"zh-hant","name":"Chinese Traditional"},{"code":"zh","name":"Chinese"}];</script><script>window.lang = "es";</script><div class="sitetoolbar__content"><div class="sitetoolbar__lang-switcher"><button class="sitetoolbar__dropdown-button" data-dropdown-toggler>ES</button><div class="sitetoolbar__dropdown-wrap"><div class="sitetoolbar__dropdown-body"><div class="sitetoolbar__lang-switcher-body"><div class="supported-langs supported-langs_toolbar"><div class="supported-langs__container"><ul class="supported-langs__list" style="height:200px"><li class="supported-langs__item"><a class="supported-langs__link" href="https://ar.javascript.info/object-copy"><span class="supported-langs__brief">AR</span><span class="supported-langs__title">عربي</span></a></li><li class="supported-langs__item"><a class="supported-langs__link" href="https://javascript.info/object-copy"><span class="supported-langs__brief">EN</span><span class="supported-langs__title">English</span></a></li><li class="supported-langs__item supported-langs__item_current"><a class="supported-langs__link" href="https://es.javascript.info/object-copy"><span class="supported-langs__brief">ES</span><span class="supported-langs__title">Español</span></a></li><li class="supported-langs__item"><a class="supported-langs__link" href="https://fa.javascript.info/object-copy"><span class="supported-langs__brief">FA</span><span class="supported-langs__title">فارسی</span></a></li><li class="supported-langs__item"><a class="supported-langs__link" href="https://fr.javascript.info/object-copy"><span class="supported-langs__brief">FR</span><span class="supported-langs__title">Français</span></a></li><li class="supported-langs__item"><a class="supported-langs__link" href="https://id.javascript.info/object-copy"><span class="supported-langs__brief">ID</span><span class="supported-langs__title">Indonesia</span></a></li></ul><ul class="supported-langs__list" style="height:200px"><li class="supported-langs__item"><a class="supported-langs__link" href="https://it.javascript.info/object-copy"><span class="supported-langs__brief">IT</span><span class="supported-langs__title">Italiano</span></a></li><li class="supported-langs__item"><a class="supported-langs__link" href="https://ja.javascript.info/object-copy"><span class="supported-langs__brief">JA</span><span class="supported-langs__title">日本語</span></a></li><li class="supported-langs__item"><a class="supported-langs__link" href="https://ko.javascript.info/object-copy"><span class="supported-langs__brief">KO</span><span class="supported-langs__title">한국어</span></a></li><li class="supported-langs__item"><a class="supported-langs__link" href="https://learn.javascript.ru/object-copy"><span class="supported-langs__brief">RU</span><span class="supported-langs__title">Русский</span></a></li><li class="supported-langs__item"><a class="supported-langs__link" href="https://tr.javascript.info/"><span class="supported-langs__brief">TR</span><span class="supported-langs__title">Türkçe</span></a></li><li class="supported-langs__item"><a class="supported-langs__link" href="https://uk.javascript.info/object-copy"><span class="supported-langs__brief">UK</span><span class="supported-langs__title">Українська</span></a></li></ul><ul class="supported-langs__list" style="height:20px"><li class="supported-langs__item"><a class="supported-langs__link" href="https://zh.javascript.info/object-copy"><span class="supported-langs__brief">ZH</span><span class="supported-langs__title">简体中文</span></a></li></ul></div><div class="supported-langs__text"><p>Queremos que este proyecto de código abierto esté disponible para personas de todo el mundo.</p> <p><a href="https://javascript.info/translate">Ayuda a traducir</a> el contenido de este tutorial a tu idioma!</p> </div></div></div></div></div></div><div class="sitetoolbar__logo-wrap"><a class="sitetoolbar__link sitetoolbar__link_logo" href="/"><img class="sitetoolbar__logo sitetoolbar__logo_normal" src="/img/sitetoolbar__logo_en.svg" width="200" alt="" role="presentation"/><img class="sitetoolbar__logo sitetoolbar__logo_normal sitetoolbar__logo_dark" src="/img/sitetoolbar__logo_en-white.svg" width="200" alt="" role="presentation"/><img class="sitetoolbar__logo sitetoolbar__logo_small" src="/img/sitetoolbar__logo_small_en.svg" width="70" alt="" role="presentation"/><img class="sitetoolbar__logo sitetoolbar__logo_small sitetoolbar__logo_dark" src="/img/sitetoolbar__logo_small_en-white.svg" width="70" alt="" role="presentation"/><script>Array.prototype.forEach.call(document.querySelectorAll("img.sitetoolbar__logo"),function(e){let t=document.createElement("object");t.type="image/svg+xml",t.className=e.className,t.style.cssText="left:0;top:0;position:absolute",t.onload=function(){t.onload=null,e.style.visibility="hidden"},t.data=e.src,e.parentNode.insertBefore(t,e)});</script></a></div><div class="sitetoolbar__nav-toggle-wrap"><button class="sitetoolbar__nav-toggle" type="button"></button></div><nav class="sitetoolbar__sections"><ul class="sitetoolbar__sections-list"></ul></nav><div class="sitetoolbar__right-button-wrap"><a class="sitetoolbar-right-button sitetoolbar-right-button_courses" href="/ebook"><span class="sitetoolbar-right-button__extra-text">Comprar</span>EPUB/PDF</a></div><div class="sitetoolbar__theme-switcher"><div class="theme-changer"><label class="theme-changer__label" for="theme-changer-input" data-tooltip="Change theme"><input class="theme-changer__input" type="checkbox" id="theme-changer-input" data-theme-changer="data-theme-changer"/><span class="theme-changer__icon theme-changer__icon_light-theme"></span><span class="theme-changer__icon theme-changer__icon_dark-theme"></span></label></div></div><div class="sitetoolbar__search-wrap"><div class="sitetoolbar__search-content"><button class="sitetoolbar__search-toggle" type="button"></button><form class="sitetoolbar__search" method="GET" action="/search"><div class="sitetoolbar__search-input"><div class="text-input"><input class="text-input__control" name="query" placeholder="Buscar en Javascript.info" required="required" type="text"/></div><button class="sitetoolbar__find" type="submit">Buscar</button></div></form></div></div></div><div class="tablet-menu"><div class="tablet-menu__line"><div class="tablet-menu__content"><form class="tablet-menu-search" action="/search/"><input class="tablet-menu-search__input" type="search" name="query" placeholder="Buscar en el tutorial" required="required"/><button class="tablet-menu-search__button" type="submit" name="type" value="articles">Buscar</button></form></div></div><div class="tablet-menu__line"><div class="tablet-menu__content"><a class="map" href="/tutorial/map" data-action="tutorial-map"><span class="map__text">Mapa del Tutorial</span></a></div></div><div class="tablet-menu__line"><div class="tablet-menu__content"><div class="theme-changer theme-changer_tablet-menu theme-changer_has-label"><label class="theme-changer__label" for="theme-changer-input-tablet" data-tooltip="Change theme"><input class="theme-changer__input" type="checkbox" id="theme-changer-input-tablet" data-theme-changer="data-theme-changer"/><span class="theme-changer__icon theme-changer__icon_light-theme"></span><span class="theme-changer__icon theme-changer__icon_dark-theme"></span><span class="theme-changer__label-text theme-changer__label-text_light-theme">Light theme</span><span class="theme-changer__label-text theme-changer__label-text_dark-theme">Dark theme</span></label></div></div></div><div class="tablet-menu__line"><div class="tablet-menu__content"><div class="share-icons"><span class="share-icons__title">Compartir</span><a class="share share_tw" href="https://twitter.com/share?url=https%3A%2F%2Fes.javascript.info%2Fobject-copy" rel="nofollow"></a><a class="share share_fb" href="https://www.facebook.com/sharer/sharer.php?s=100&amp;p%5Burl%5D=https%3A%2F%2Fes.javascript.info%2Fobject-copy" rel="nofollow"></a></div></div></div><div class="tablet-menu__line"><div class="tablet-menu__content"><select class="tablet-menu__nav input-select input-select input-select_small" onchange="if(this.value) window.location.href=this.value"><option value="https://ar.javascript.info/object-copy">عربي</option><option value="https://javascript.info/object-copy">English</option><option value="https://es.javascript.info/object-copy" selected>Español</option><option value="https://fa.javascript.info/object-copy">فارسی</option><option value="https://fr.javascript.info/object-copy">Français</option><option value="https://id.javascript.info/object-copy">Indonesia</option><option value="https://it.javascript.info/object-copy">Italiano</option><option value="https://ja.javascript.info/object-copy">日本語</option><option value="https://ko.javascript.info/object-copy">한국어</option><option value="https://learn.javascript.ru/object-copy">Русский</option><option value="https://tr.javascript.info/">Türkçe</option><option value="https://uk.javascript.info/object-copy">Українська</option><option value="https://zh.javascript.info/object-copy">简体中文</option></select></div></div></div><progress class="tutorial-progress" data-sticky value="30" max="94" data-tooltip="Lección 30 de 94"></progress></div><div class="page page_sidebar_on page_inner_padding"><script>if(localStorage.noSidebar){document.querySelector(".page").classList.remove("page_sidebar_on");let e=document.querySelector(".page-wrapper");e&&e.classList.remove("page-wrapper_sidebar_on")}setTimeout(function(){document.querySelector(".page").classList.add("page_sidebar-animation-on")});</script><div class="page__inner"><main class="main main_width-limit"><header class="main__header"><div class="main__header-inner"><div class="main__header-group"><ol class="breadcrumbs"><li class="breadcrumbs__item breadcrumbs__item_home"><a class="breadcrumbs__link" href="/"><span class="breadcrumbs__hidden-text">Tutorial</span></a></li><li class="breadcrumbs__item" id="breadcrumb-1"><a class="breadcrumbs__link" href="/js"><span>El lenguaje JavaScript</span></a></li><li class="breadcrumbs__item" id="breadcrumb-2"><a class="breadcrumbs__link" href="/object-basics"><span>Objetos: lo básico</span></a></li><script type="application/ld+json">{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"name":"Tutorial","item":"https://es.javascript.info/"},{"@type":"ListItem","position":2,"name":"El lenguaje JavaScript","item":"https://es.javascript.info/js"},{"@type":"ListItem","position":3,"name":"Objetos: lo básico","item":"https://es.javascript.info/object-basics"}]}</script></ol><div class="updated-at" data-tooltip="Última actualización el 4 de octubre de 2022"><div class="updated-at__content">4 de octubre de 2022</div></div></div><h1 class="main__header-title">Referencias de objetos y copia</h1></div></header><div class="content"><article class="formatted" itemscope itemtype="http://schema.org/TechArticle"><meta itemprop="name" content="Referencias de objetos y copia"><div itemprop="author" itemscope itemtype="http://schema.org/Person"><meta itemprop="email" content="iliakan@gmail.com"><meta itemprop="name" content="Ilya Kantor"></div><div itemprop="articleBody"><p>Una de las diferencias fundamentales entre objetos y primitivos es que los objetos son almacenados y copiados “por referencia”, en cambio los primitivos: strings, number, boolean, etc.; son asignados y copiados “como un valor completo”.</p> <p>Esto es fácil de entender si miramos un poco “bajo cubierta” de lo que pasa cuando copiamos por valor.</p> <p>Empecemos por un primitivo como string.</p> <p>Aquí ponemos una copia de <code>message</code> en <code>phrase</code>:</p> <div id="eq3trarud1" data-trusted="1" class="code-example"> <div class="codebox code-example__codebox"> <div class="codebox__code" data-code="1"> <pre class="line-numbers language-javascript"><code>let message = &quot;Hello!&quot;; let phrase = message;</code></pre> </div> </div> </div><p>Como resultado tenemos dos variables independientes, cada una almacenando la cadena <code>&quot;Hello!&quot;</code>.</p> <figure><div class="image" style="width:359px"> <div class="image__ratio" style="padding-top:39.83286908077994%"></div> <object type="image/svg+xml" data="/article/object-copy/variable-copy-value.svg" width="359" height="143" class="image__image" data-use-theme> <img src="/article/object-copy/variable-copy-value.svg" alt="" width="359" height="143"> </object> </div></figure><p>Bastante obvio, ¿verdad?</p> <p>Los objetos no son así.</p> <p><strong>Una variable no almacena el objeto mismo sino su “dirección en memoria”, en otras palabras “una referencia” a él.</strong></p> <p>Veamos un ejemplo de tal variable:</p> <div id="z5xy2ze2fz" data-trusted="1" class="code-example"> <div class="codebox code-example__codebox"> <div class="codebox__code" data-code="1"> <pre class="line-numbers language-javascript"><code>let user = { name: &quot;John&quot; };</code></pre> </div> </div> </div><p>Y así es como se almacena en la memoria:</p> <figure><div class="image" style="width:370px"> <div class="image__ratio" style="padding-top:67.29729729729729%"></div> <object type="image/svg+xml" data="/article/object-copy/variable-contains-reference.svg" width="370" height="249" class="image__image" data-use-theme> <img src="/article/object-copy/variable-contains-reference.svg" alt="" width="370" height="249"> </object> </div></figure><p>El objeto es almacenado en algún lugar de la memoria (a la derecha de la imagen), mientras que la variable <code>user</code> (a la izquierda) tiene una “referencia” a él.</p> <p>Podemos pensar de una variable objeto, como <code>user</code>, como una hoja de papel con la dirección del objeto escrita en ella.</p> <p>Cuando ejecutamos acciones con el objeto, por ejemplo tomar una propiedad <code>user.name</code>, el motor JavaScript busca aquella dirección y ejecuta la operación en el objeto mismo.</p> <p>Ahora, por qué esto es importante.</p> <p><strong>Cuando una variable de objeto es copiada, se copia solo la referencia. El objeto no es duplicado.</strong></p> <p>Por ejemplo:</p> <div id="ti1rohd0xs" data-trusted="1" class="code-example"> <div class="codebox code-example__codebox"> <div class="codebox__code" data-code="1"> <pre class="line-numbers language-javascript"><code>let user = { name: &quot;John&quot; }; let admin = user; // copia la referencia</code></pre> </div> </div> </div><p>Ahora tenemos dos variables, cada una con una referencia al mismo objeto:</p> <figure><div class="image" style="width:599px"> <div class="image__ratio" style="padding-top:43.40567612687813%"></div> <object type="image/svg+xml" data="/article/object-copy/variable-copy-reference.svg" width="599" height="260" class="image__image" data-use-theme> <img src="/article/object-copy/variable-copy-reference.svg" alt="" width="599" height="260"> </object> </div></figure><p>Como puedes ver, aún hay un objeto, ahora con dos variables haciendo referencia a él.</p> <p>Podemos usar cualquiera de las variables para acceder al objeto y modificar su contenido:</p> <div id="n8xpoo06ea" data-trusted="1" class="code-example" data-highlight="[{&quot;start&quot;:6,&quot;cols&quot;:[{&quot;start&quot;:6,&quot;end&quot;:15}]},{&quot;start&quot;:4,&quot;end&quot;:4}]"> <div class="codebox code-example__codebox"> <div class="toolbar codebox__toolbar"> <div class="toolbar__tool"> <a href="#" title="ejecutar" data-action="run" class="toolbar__button toolbar__button_run"></a> </div> <div class="toolbar__tool"> <a href="#" title="abrir en entorno controlado" target="_blank" data-action="edit" class="toolbar__button toolbar__button_edit"></a> </div> </div> <div class="codebox__code" data-code="1"> <pre class="line-numbers language-javascript"><code>let user = { name: 'John' }; let admin = user; admin.name = 'Pete'; // cambiado por la referencia &quot;admin&quot; alert(user.name); // 'Pete', los cambios se ven desde la referencia &quot;user&quot;</code></pre> </div> </div> </div><p>Es como si tuviéramos un gabinete con dos llaves y usáramos una de ellas (<code>admin</code>) para acceder a él y hacer cambios. Si más tarde usamos la llave (<code>user</code>), estaríamos abriendo el mismo gabinete y accediendo al contenido cambiado.</p> <h2><a class="main__anchor" name="comparacion-por-referencia" href="#comparacion-por-referencia">Comparación por referencia</a></h2><p>Dos objetos son iguales solamente si ellos son el mismo objeto.</p> <p>Por ejemplo, aquí <code>a</code> y <code>b</code> tienen referencias al mismo objeto, por lo tanto son iguales:</p> <div id="6gqxdqhg3y" data-trusted="1" class="code-example"> <div class="codebox code-example__codebox"> <div class="toolbar codebox__toolbar"> <div class="toolbar__tool"> <a href="#" title="ejecutar" data-action="run" class="toolbar__button toolbar__button_run"></a> </div> <div class="toolbar__tool"> <a href="#" title="abrir en entorno controlado" target="_blank" data-action="edit" class="toolbar__button toolbar__button_edit"></a> </div> </div> <div class="codebox__code" data-code="1"> <pre class="line-numbers language-javascript"><code>let a = {}; let b = a; // copia la referencia alert( a == b ); // true, verdadero. Ambas variables hacen referencia al mismo objeto alert( a === b ); // true</code></pre> </div> </div> </div><p>Y aquí dos objetos independientes no son iguales, aunque se vean iguales (ambos están vacíos):</p> <div id="782ogn6v8n" data-trusted="1" class="code-example"> <div class="codebox code-example__codebox"> <div class="toolbar codebox__toolbar"> <div class="toolbar__tool"> <a href="#" title="ejecutar" data-action="run" class="toolbar__button toolbar__button_run"></a> </div> <div class="toolbar__tool"> <a href="#" title="abrir en entorno controlado" target="_blank" data-action="edit" class="toolbar__button toolbar__button_edit"></a> </div> </div> <div class="codebox__code" data-code="1"> <pre class="line-numbers language-javascript"><code>let a = {}; let b = {}; // dos objetos independientes alert( a == b ); // false</code></pre> </div> </div> </div><p>Para comparaciones como <code>obj1 &gt; obj2</code>, o comparaciones contra un primitivo <code>obj == 5</code>, los objetos son convertidos a primitivos. Estudiaremos cómo funciona la conversión de objetos pronto, pero a decir verdad tales comparaciones ocurren raramente y suelen ser errores de código.</p> <div class="important important_smart"> <div class="important__header"><span class="important__type">Los objetos </span></div> <div class="important__content"><p>Un efecto importante de almacenar objetos como referencias es que un objeto declarado como <code>const</code> <em>puede</em> ser modificado.</p> <p>Por ejemplo:</p> <div id="kbzvow2mbh" data-trusted="1" class="code-example" data-highlight="[{&quot;start&quot;:4,&quot;end&quot;:4}]"> <div class="codebox code-example__codebox"> <div class="toolbar codebox__toolbar"> <div class="toolbar__tool"> <a href="#" title="ejecutar" data-action="run" class="toolbar__button toolbar__button_run"></a> </div> <div class="toolbar__tool"> <a href="#" title="abrir en entorno controlado" target="_blank" data-action="edit" class="toolbar__button toolbar__button_edit"></a> </div> </div> <div class="codebox__code" data-code="1"> <pre class="line-numbers language-javascript"><code>const user = { name: &quot;John&quot; }; user.name = &quot;Pete&quot;; // (*) alert(user.name); // Pete</code></pre> </div> </div> </div><p>Puede parecer que la línea <code>(*)</code> causaría un error, pero no lo hace. El valor de <code>user</code> es constante, este valor debe siempre hacer referencia al mismo objeto, pero las propiedades de dicho objeto pueden cambiar.</p> <p>En otras palabras: <code>const user</code> da un error solamente si tratamos de establecer <code>user=...</code> como un todo.</p> <p>Dicho esto, si realmente necesitamos hacer constantes las propiedades del objeto, también es posible, pero usando métodos totalmente diferentes. Los mencionaremos en el capítulo <a href="/property-descriptors">Indicadores y descriptores de propiedad</a>.</p> </div></div> <h2><a class="main__anchor" name="cloning-and-merging-object-assign" href="#cloning-and-merging-object-assign">Clonación y mezcla, Object.assign</a></h2><p>Entonces copiar una variable de objeto crea una referencia adicional al mismo objeto.</p> <p>Pero ¿y si necesitamos duplicar un objeto?</p> <p>Podemos crear un nuevo objeto y replicar la estructura del existente iterando a través de sus propiedades y copiándolas en el nivel primitivo.</p> <p>Como esto:</p> <div id="rxrm1cgtym" data-trusted="1" class="code-example" data-highlight="[{&quot;start&quot;:5,&quot;end&quot;:10}]"> <div class="codebox code-example__codebox"> <div class="toolbar codebox__toolbar"> <div class="toolbar__tool"> <a href="#" title="ejecutar" data-action="run" class="toolbar__button toolbar__button_run"></a> </div> <div class="toolbar__tool"> <a href="#" title="abrir en entorno controlado" target="_blank" data-action="edit" class="toolbar__button toolbar__button_edit"></a> </div> </div> <div class="codebox__code" data-code="1"> <pre class="line-numbers language-javascript"><code>let user = { name: &quot;John&quot;, age: 30 }; let clone = {}; // el nuevo objeto vacío // copiemos todas las propiedades de user en él for (let key in user) { clone[key] = user[key]; } // ahora clone es un objeto totalmente independiente con el mismo contenido clone.name = &quot;Pete&quot;; // cambiamos datos en él alert( user.name ); // John aún está en el objeto original</code></pre> </div> </div> </div><p>También podemos usar el método <a href="https://developer.mozilla.org/es/docs/Web/JavaScript/Referencia/Objetos_globales/Object/assign">Object.assign</a>.</p> <p>La sintaxis es:</p> <div id="lj560ef07o" data-trusted="1" class="code-example"> <div class="codebox code-example__codebox"> <div class="codebox__code" data-code="1"> <pre class="line-numbers language-javascript"><code>Object.assign(dest, ...sources)</code></pre> </div> </div> </div><ul> <li>El primer argumento <code>dest</code> es el objeto destinatario.</li> <li>Los argumentos que siguen son una lista de objetos fuentes.</li> </ul> <p>Esto copia las propiedades de todos los objetos fuentes dentro del destino <code>dest</code> y lo devuelve como resultado</p> <p>Por ejemplo, tenemos el objeto <code>user</code>, agreguemos un par de permisos:</p> <div id="3xdnb7dl02" data-trusted="1" class="code-example" data-highlight="[{&quot;start&quot;:5,&quot;end&quot;:6}]"> <div class="codebox code-example__codebox"> <div class="toolbar codebox__toolbar"> <div class="toolbar__tool"> <a href="#" title="ejecutar" data-action="run" class="toolbar__button toolbar__button_run"></a> </div> <div class="toolbar__tool"> <a href="#" title="abrir en entorno controlado" target="_blank" data-action="edit" class="toolbar__button toolbar__button_edit"></a> </div> </div> <div class="codebox__code" data-code="1"> <pre class="line-numbers language-javascript"><code>let user = { name: &quot;John&quot; }; let permissions1 = { canView: true }; let permissions2 = { canEdit: true }; // copia todas las propiedades desde permissions1 y permissions2 en user Object.assign(user, permissions1, permissions2); // ahora es user = { name: &quot;John&quot;, canView: true, canEdit: true } alert(user.name); // John alert(user.canView); // true alert(user.canEdit); // true</code></pre> </div> </div> </div><p>Si la propiedad por copiar ya existe, se sobrescribe:</p> <div id="znbpkm6eqo" data-trusted="1" class="code-example"> <div class="codebox code-example__codebox"> <div class="toolbar codebox__toolbar"> <div class="toolbar__tool"> <a href="#" title="ejecutar" data-action="run" class="toolbar__button toolbar__button_run"></a> </div> <div class="toolbar__tool"> <a href="#" title="abrir en entorno controlado" target="_blank" data-action="edit" class="toolbar__button toolbar__button_edit"></a> </div> </div> <div class="codebox__code" data-code="1"> <pre class="line-numbers language-javascript"><code>let user = { name: &quot;John&quot; }; Object.assign(user, { name: &quot;Pete&quot; }); alert(user.name); // ahora user = { name: &quot;Pete&quot; }</code></pre> </div> </div> </div><p>También podemos usar <code>Object.assign</code> para hacer una clonación simple:</p> <div id="1cpadjykvi" data-trusted="1" class="code-example" data-highlight="[{&quot;start&quot;:5,&quot;end&quot;:5}]"> <div class="codebox code-example__codebox"> <div class="toolbar codebox__toolbar"> <div class="toolbar__tool"> <a href="#" title="ejecutar" data-action="run" class="toolbar__button toolbar__button_run"></a> </div> <div class="toolbar__tool"> <a href="#" title="abrir en entorno controlado" target="_blank" data-action="edit" class="toolbar__button toolbar__button_edit"></a> </div> </div> <div class="codebox__code" data-code="1"> <pre class="line-numbers language-javascript"><code>let user = { name: &quot;John&quot;, age: 30 }; let clone = Object.assign({}, user); alert(clone.name); // John alert(clone.age); // 30</code></pre> </div> </div> </div><p>Aquí, copia todas las propiedades de <code>user</code> en un objeto vacío y lo devuelve.</p> <p>También hay otras formas de clonar un objeto, por ejemplo usando la <a href="/rest-parameters-spread">sintaxis spread</a> <code>clone = {...user}</code>, cubierto más adelante en el tutorial.</p> <h2><a class="main__anchor" name="clonacion-anidada" href="#clonacion-anidada">Clonación anidada</a></h2><p>Hasta ahora supusimos que todas las propiedades de <code>user</code> eran primitivas. Pero las propiedades pueden ser referencias a otros objetos.</p> <p>Como esto:</p> <div id="g3dzew43h2" data-trusted="1" class="code-example"> <div class="codebox code-example__codebox"> <div class="toolbar codebox__toolbar"> <div class="toolbar__tool"> <a href="#" title="ejecutar" data-action="run" class="toolbar__button toolbar__button_run"></a> </div> <div class="toolbar__tool"> <a href="#" title="abrir en entorno controlado" target="_blank" data-action="edit" class="toolbar__button toolbar__button_edit"></a> </div> </div> <div class="codebox__code" data-code="1"> <pre class="line-numbers language-javascript"><code>let user = { name: &quot;John&quot;, sizes: { height: 182, width: 50 } }; alert( user.sizes.height ); // 182</code></pre> </div> </div> </div><p>Ahora no es suficiente copiar <code>clone.sizes = user.sizes</code>, porque <code>user.sizes</code> es un objeto y será copiado por referencia. Entonces <code>clone</code> y <code>user</code> compartirán las mismas tallas (.sizes):</p> <div id="snw2hccyxp" data-trusted="1" class="code-example"> <div class="codebox code-example__codebox"> <div class="toolbar codebox__toolbar"> <div class="toolbar__tool"> <a href="#" title="ejecutar" data-action="run" class="toolbar__button toolbar__button_run"></a> </div> <div class="toolbar__tool"> <a href="#" title="abrir en entorno controlado" target="_blank" data-action="edit" class="toolbar__button toolbar__button_edit"></a> </div> </div> <div class="codebox__code" data-code="1"> <pre class="line-numbers language-javascript"><code>let user = { name: &quot;John&quot;, sizes: { height: 182, width: 50 } }; let clone = Object.assign({}, user); alert( user.sizes === clone.sizes ); // true, el mimo objeto // user y clone comparten sizes user.sizes.width = 60; // cambia la propiedad en un lugar alert(clone.sizes.width); // 60, obtiene el resultado desde el otro</code></pre> </div> </div> </div><p>Para corregir esto, debemos hacer que <code>user</code> y <code>clone</code> sean objetos completamente separados, debemos usar un bucle que examine cada valor de <code>user[key]</code> y, si es un objeto, que replique su estructura también. Esto es conocido como “clonación profunda” o “clonación estructurada”. Existe un método <a href="https://developer.mozilla.org/en-US/docs/Web/API/structuredClone">structuredClone</a> que implementa tal clonación profunda.</p> <h3><a class="main__anchor" name="structuredclone" href="#structuredclone">structuredClone</a></h3><p>La llamada a <code>structuredClone(object)</code> clona el <code>object</code> con todas sus propiedadas anidadas.</p> <p>Podemos usarlo en nuestro ejemplo:</p> <div id="pcjub9eq5a" data-trusted="1" class="code-example" data-highlight="[{&quot;start&quot;:8,&quot;end&quot;:8}]"> <div class="codebox code-example__codebox"> <div class="toolbar codebox__toolbar"> <div class="toolbar__tool"> <a href="#" title="ejecutar" data-action="run" class="toolbar__button toolbar__button_run"></a> </div> <div class="toolbar__tool"> <a href="#" title="abrir en entorno controlado" target="_blank" data-action="edit" class="toolbar__button toolbar__button_edit"></a> </div> </div> <div class="codebox__code" data-code="1"> <pre class="line-numbers language-javascript"><code>let user = { name: &quot;John&quot;, sizes: { height: 182, width: 50 } }; let clone = structuredClone(user); alert( user.sizes === clone.sizes ); // false, objetos diferentes // ahora user y clone están totalmente separados user.sizes.width = 60; // cambia una propiedad de un lugar alert(clone.sizes.width); // 50, no están relacionados</code></pre> </div> </div> </div><p>El método <code>structuredClone</code> puede clonar la mayoría de los tipos de datos, como objetos, arrays, valores primitivos.</p> <p>También soporta referencias circulares, cuando una propiedad de objeto referencia el objeto mismo (directamente o por una cadena de referencias).</p> <p>Por ejemplo:</p> <div id="2zrlt4vm4y" data-trusted="1" class="code-example"> <div class="codebox code-example__codebox"> <div class="toolbar codebox__toolbar"> <div class="toolbar__tool"> <a href="#" title="ejecutar" data-action="run" class="toolbar__button toolbar__button_run"></a> </div> <div class="toolbar__tool"> <a href="#" title="abrir en entorno controlado" target="_blank" data-action="edit" class="toolbar__button toolbar__button_edit"></a> </div> </div> <div class="codebox__code" data-code="1"> <pre class="line-numbers language-javascript"><code>let user = {}; // hagamos una referencia circular // user.me referencia user a sí mismo user.me = user; let clone = structuredClone(user); alert(clone.me === clone); // true</code></pre> </div> </div> </div><p>Como puedes ver, <code>clone.me</code> hace referencia a <code>clone</code>, no a <code>user</code>! Así que la referencia circular fue clonada correctamente también.</p> <p>Pero hay casos en que <code>structuredClone</code> falla.</p> <p>Por ejemplo, cuando un objeto tienen una propiedad “function”:</p> <div id="mobx9650vl" data-trusted="1" class="code-example"> <div class="codebox code-example__codebox"> <div class="toolbar codebox__toolbar"> <div class="toolbar__tool"> <a href="#" title="ejecutar" data-action="run" class="toolbar__button toolbar__button_run"></a> </div> <div class="toolbar__tool"> <a href="#" title="abrir en entorno controlado" target="_blank" data-action="edit" class="toolbar__button toolbar__button_edit"></a> </div> </div> <div class="codebox__code" data-code="1"> <pre class="line-numbers language-javascript"><code>// error structuredClone({ f: function() {} });</code></pre> </div> </div> </div><p>Las propiedades de función no están soportadas.</p> <p>Para manejar estos casos complejos podemos necesitar una combinación de métodos de clonación, escribir código personalizado o, para no reinventar la rueda, tomar una implementación existente, por ejemplo <a href="https://lodash.com/docs#cloneDeep">_.cloneDeep(obj)</a> de la librería JavaScript <a href="https://lodash.com">lodash</a>.</p> <h2><a class="main__anchor" name="resumen" href="#resumen">Resumen</a></h2><p>Los objetos son asignados y copiados por referencia. En otras palabras, una variable almacena no el valor del objeto sino una referencia (la dirección en la memoria) del valor. Entonces, copiar tal variable o pasarla como argumento de función copia la referencia, no el objeto.</p> <p>Todas la operaciones a través de referencias copiadas (como agregar y borrar propiedades) son efectuadas en el mismo y único objeto .</p> <p>Para hacer una “verdadera copia” (un clon), podemos usar <code>Object.assign</code> para la denominada “clonación superficial” (los objetos anidados son copiados por referencia), o la función de “clonación profunda” <code>structuredClone</code> o usar una implementación personalizada como <a href="https://lodash.com/docs#cloneDeep">_.cloneDeep(obj)</a>.</p> </div></article></div><div class="page__nav-wrap"><a class="page__nav page__nav_prev" href="/object" data-tooltip="Objetos"><span class="page__nav-text"><span class="page__nav-text-shortcut"></span></span><span class="page__nav-text-alternate">Lección anterior</span></a><a class="page__nav page__nav_next" href="/garbage-collection" data-tooltip="Recolección de basura"><span class="page__nav-text"><span class="page__nav-text-shortcut"></span></span><span class="page__nav-text-alternate">Próxima lección</span></a></div><div class="article-tablet-foot tablet-only"><div class="article-tablet-foot__layout"><div class="share-icons"><span class="share-icons__title">Compartir</span><a class="share share_tw" href="https://twitter.com/share?url=https%3A%2F%2Fes.javascript.info%2Fobject-copy" rel="nofollow"></a><a class="share share_fb" href="https://www.facebook.com/sharer/sharer.php?s=100&amp;p%5Burl%5D=https%3A%2F%2Fes.javascript.info%2Fobject-copy" rel="nofollow"></a></div><div class="article-tablet-foot__map"><a class="map" href="/tutorial/map" data-action="tutorial-map"><span class="map__text">Mapa del Tutorial</span></a></div></div></div><div class="comments formatted" id="comments"><div class="comments__header"><h2 class="comments__header-title"><a href="#comments" name="comments">Comentarios</a></h2><div class="comments__read-before"><span class="comments__read-before-link">lea esto antes de comentar…</span><div class="comments__read-before-popup"><div class="comments__read-before-popup-i"><ul><li>Si tiene sugerencias sobre qué mejorar, por favor <a href="https://github.com/javascript-tutorial/en.javascript.info/issues/new">enviar una propuesta de GitHub</a> o una solicitud de extracción en lugar de comentar.</li><li>Si no puede entender algo en el artículo, por favor explique.</li><li>Para insertar algunas palabras de código, use la etiqueta <code>&lt;code&gt;</code>, para varias líneas – envolverlas en la etiqueta <code>&lt;pre&gt;</code>, para más de 10 líneas – utilice una entorno controlado (sandbox) (<a href='https://plnkr.co/edit/?p=preview'>plnkr</a>, <a href='https://jsbin.com'>jsbin</a>, <a href='http://codepen.io'>codepen</a>…)</li></ul></div></div></div></div><div id="disqus_thread"></div><script>var disqus_config = function() { if (!this.page) this.page = {}; Object.assign(this.page, {"url":"https:\/\/es.javascript.info\/object-copy","identifier":"\/object-copy"}); };</script><script>var disqus_shortname = "es-javascript-info";</script><script>var disqus_enabled = true;</script></div></script></main></div><div class="sidebar page__sidebar sidebar sidebar_sticky-footer"><button class="sidebar__toggle" data-sidebar-toggle></button><a class="map" href="/tutorial/map" data-action="tutorial-map" data-tooltip="Mapa del Tutorial"></a><div class="sidebar__inner"><div class="sidebar__content"><div class="sidebar__section"><h4 class="sidebar__section-title">Capítulo</h4><nav class="sidebar__navigation"><ul class="sidebar__navigation-links"><li class="sidebar__navigation-link"><a class="sidebar__link" href="/object-basics">Objetos: lo básico</a></li></ul></nav></div><div class="sidebar__section"><h4 class="sidebar__section-title">Navegación de lección</h4><nav class="sidebar__navigation"><ul class="sidebar__navigation-links"><li class="sidebar__navigation-link"><a class="sidebar__link" href="#comparacion-por-referencia">Comparación por referencia</a></li><li class="sidebar__navigation-link"><a class="sidebar__link" href="#cloning-and-merging-object-assign">Clonación y mezcla, Object.assign</a></li><li class="sidebar__navigation-link"><a class="sidebar__link" href="#clonacion-anidada">Clonación anidada</a></li><li class="sidebar__navigation-link"><a class="sidebar__link" href="#resumen">Resumen</a></li></ul></nav></div><div class="sidebar__section"><nav class="sidebar__navigation"><ul class="sidebar__navigation-links"><li class="sidebar__navigation-link"><a class="sidebar__link" href="#comments">Comentarios</a></li></ul></nav></div><div class="sidebar__section"><div class="sidebar__section-title">Compartir</div><a class="share share_tw sidebar__share" href="https://twitter.com/share?url=https%3A%2F%2Fes.javascript.info%2Fobject-copy" rel="nofollow"></a><a class="share share_fb sidebar__share" href="https://www.facebook.com/sharer/sharer.php?s=100&amp;p[url]=https%3A%2F%2Fes.javascript.info%2Fobject-copy" rel="nofollow"></a></div><div class="sidebar__section"><a class="sidebar__link" href="https://github.com/javascript-tutorial/es.javascript.info/blob/master/1-js/04-object-basics/02-object-copy" rel="nofollow">Editar en GitHub</a></div></div></div></div></div></div><div class="page-footer"><ul class="page-footer__list"><li class="page-footer__item page-footer__item_copy">©&nbsp;2007—2025&nbsp; Ilya Kantor</li><li class="page-footer__item page-footer__item_about"><a class="page-footer__link" href="/about">acerca del proyecto</a></li><li class="page-footer__item page-footer__item_contact"><a class="page-footer__link" href="/about#contact-us">contáctenos</a></li></ul></div></body></html>

Pages: 1 2 3 4 5 6 7 8 9 10