ECMAScript 5 _.extend

A algunos ya os he comentado los problemas que NC Zakas comenta con el _.extend de underscore y los getters:

var a = {
  init: function() {
    this.list = [];
  },

  get first() {
    return this.list[0];
  }
};

O

var a = {
  init: function() {
    this.list = [];
  }
};

Object.defineProperty(a, 'first', {
  get: function() {
    return this.list[0];
  }
});

Y que si hacemos _.extend(a) va a fallar porque intentará hacer result.first = a.first ejecutando el getter. Pero como aún no hemos llamado al .init() en a porque solo es un prototipo, la propiedad .list es undefined produciendo un error.

Pues bien, yo creía que esto se solucionaba extrayendo el descriptor de la propiedad y usando ese mismo descriptor para copiar la propiedad al nuevo objeto:

function extend(obj) {
  var result = {};
  var properties = Object.keys(obj);

  properties.forEach(function(prop) {
    var descriptor = Object.getOwnPropertyDescriptor(obj, prop);
    Object.defineProperty(result, prop, descriptor);
  });

  return result;
}

Pero he usado esto en la librería de promises y me he dado cuenta que solo hereda las propiedades directas, tanto Object.keys como Object.getOwnPropertyDescriptor solo funcionan si la propiedad está directamente declarada en el objeto y no en ninguno de sus prototipos. Y no hay ninguna forma de decir Object.getPropertyDescriptorFromHimOrHisPrototypes() así que la única forma es recorrer todos los prototipos.

function extend(obj) {
  var result = {};
  var proto = obj;

  while (proto) {
    Object.keys(proto).forEach(function(prop) {
      var descriptor = Object.getOwnPropertyDescriptor(proto, prop);
      Object.defineProperty(result, prop, descriptor);
    });

    proto = Object.getPrototypeOf(proto);
  }

  return result;
}

Pero eso tampoco funciona del todo bien porque las propiedades de los ancestros se impondrían sobre las propiedades propias del objeto. Así que primero hay que empezar por el último prototipo y acabar por el propio objeto

function extend(obj) {
  var result = {};
  var proto = obj;
  var protos = [];

  while (proto) {
    protos.push(proto);
    proto = Object.getPrototypeOf(proto);
  }

  protos.reverse().forEach(function(ancestor) {
    Object.keys(ancestor).forEach(function(prop) {
      var descriptor = Object.getOwnPropertyDescriptor(ancestor, prop);
      Object.defineProperty(result, prop, descriptor);
    });
  });

  return result;
}

Y esto ya funciona, pero le falta un detallito, mediante el property descriptor se puede poner que una propiedad no sea enumerable por lo que no se interará sobre ella con un for .. in .. ni con Object.keys pero si las podemos obtener si utilizamos Object.getOwnPropertyNames (Fuente: MDN). Así que remplazando Object.keys con Object.getOwnPropertyNames esta vez si (espero, rezo, suplico -.-) tenemos una función que crea una copia de todas las propiedades propias y heredadas de un objeto.

function ecma5extend(obj) {
  var proto = obj;
  var protos = [];
  var result = {};

  while (proto) {
    protos.push(proto);
    proto = Object.getPrototypeOf(proto);
  }

  protos.reverse().forEach(function(ancestor) {
    Object.getOwnPropertyNames(ancestor).forEach(function(prop) {
      var descriptor = Object.getOwnPropertyDescriptor(ancestor, prop);
      Object.defineProperty(result, prop, descriptor);
    });
  });

  return result;
}

Como al final el código ha quedado bastante más complejo de lo que me gustaría lo he apuntado en un Gist que podría venirles bien.

186 thoughts on “ECMAScript 5 _.extend

  1. It is the best time to make a few plans for the longer term
    and it’s time to be happy. I’ve read this submit and if I could I
    desire to counsel you few attention-grabbing things or advice.
    Maybe you can write next articles referring to this article.
    I desire to read more issues approximately it!

  2. Thanks for your write-up. One other thing is when you are selling your property all on your own, one of the challenges you need to be conscious of upfront is how to deal with property inspection reviews. As a FSBO retailer, the key towards successfully moving your property as well as saving money about real estate agent profits is information. The more you are aware of, the better your home sales effort will probably be. One area exactly where this is particularly essential is information about home inspections.

  3. Its such as you read my mind! You seem to know a lot about this, such as you wrote the
    guide in it or something. I feel that you just can do with a
    few percent to power the message house a
    bit, but other than that, this is great blog. An excellent read.

    I’ll definitely be back.

  4. It’s the best time to make some plans for the future and it is time to be happy.
    I’ve read this post and if I could I desire to suggest
    you few interesting things or suggestions. Perhaps you could write next
    articles referring to this article. I wish to read more things about it!

  5. In my opinion that a property foreclosures can have a significant effect on the borrower’s life. Property foreclosures can have a 6 to decade negative effect on a applicant’s credit report. The borrower who have applied for a home loan or any loans even, knows that a worse credit rating is, the more complicated it is to have a decent loan. In addition, it can affect a new borrower’s capability to find a decent place to lease or hire, if that results in being the alternative real estate solution. Good blog post.

  6. I have been browsing online more than 4 hours today, yet I never
    found any interesting article like yours. It is pretty worth
    enough for me. In my opinion, if all webmasters and bloggers made good content
    as you did, the web will be much more useful than ever before.

  7. I have realized that car insurance firms know the motors which are liable to accidents as well as other risks. Additionally they know what types of cars are inclined to higher risk and also the higher risk they’ve the higher a premium fee. Understanding the very simple basics with car insurance will help you choose the right kind of insurance policy which will take care of your wants in case you happen to be involved in an accident. Thank you sharing a ideas on your own blog.

  8. Howdy just wanted to give you a quick heads up. The words
    in your article seem to be running off the screen in Ie. I’m not sure if this is a
    format issue or something to do with browser compatibility
    but I figured I’d post to let you know. The layout look great
    though! Hope you get the issue resolved soon. Cheers

  9. I have been browsing online greater than three hours lately, but I by
    no means discovered any interesting article like yours. It’s beautiful value sufficient for me.
    Personally, if all site owners and bloggers made just right content
    material as you did, the internet will be much more useful
    than ever before.

  10. Hi there just wanted to give you a quick heads up.

    The words in your post seem to be running off the screen in Firefox.
    I’m not sure if this is a formatting issue or something to do with web
    browser compatibility but I thought I’d post to let you know.
    The design and style look great though! Hope you get the problem solved soon. Cheers

  11. It’s the best time to make some plans for the future
    and it’s time to be happy. I have read this post and if
    I could I wish to suggest you few interesting things or advice.
    Perhaps you can write next articles referring to this article.
    I want to read more things about it!

  12. Thanks for the advice on credit repair on your site. What I would advice people is usually to give up the mentality they will buy right now and shell out later. Like a society we tend to repeat this for many things. This includes holidays, furniture, as well as items we’d like. However, you need to separate your wants from all the needs. When you’re working to raise your credit score you really have to make some sacrifices. For example you’ll be able to shop online to save money or you can look at second hand merchants instead of expensive department stores pertaining to clothing.

  13. I’ve been browsing online more than 3 hours today, yet I never found any
    interesting article like yours. It’s pretty worth enough
    for me. In my opinion, if all site owners and bloggers made good content as you did, the net
    will be much more useful than ever before.

  14. Hey just wanted to give you a quick heads up.
    The text in your content seem to be running off the screen in Internet
    explorer. I’m not sure if this is a format issue or something to do
    with browser compatibility but I figured I’d post to let you know.
    The design look great though! Hope you get the issue solved soon. Many thanks

  15. It’s perfect time to make some plans for the future and it is time to be happy.

    I’ve read this post and if I could I want to suggest you some interesting
    things or tips. Perhaps you could write next articles referring
    to this article. I desire to read more things about it!

  16. Thank you for every other informative site. Where else may just I get that type of information written in such a perfect means? I’ve a undertaking that I am just now working on, and I’ve been on the glance out for such information.

  17. Hey there would you mind letting me know which webhost you’re
    utilizing? I’ve loaded your blog in 3 completely
    different web browsers and I must say this blog loads a lot
    faster then most. Can you recommend a good web hosting provider at a honest
    price? Thank you, I appreciate it!

  18. It is the best time to make some plans for the future and it is time to be
    happy. I’ve read this post and if I could I desire to suggest you some interesting things or tips.
    Maybe you could write next articles referring
    to this article. I wish to read more things about it!

  19. I’ve been surfing online more than three hours today,
    yet I never found any interesting article like yours.
    It is pretty worth enough for me. In my view, if all site owners and
    bloggers made good content as you did, the internet will be much more useful
    than ever before.

Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *