{"id":2255,"date":"2015-10-13T06:37:32","date_gmt":"2015-10-13T06:37:32","guid":{"rendered":"http:\/\/www.nikola-breznjak.com\/blog\/?p=2255"},"modified":"2015-10-13T06:40:50","modified_gmt":"2015-10-13T06:40:50","slug":"how-to-override-a-function-when-creating-a-new-object-in-the-prototypal-inheritance","status":"publish","type":"post","link":"https:\/\/nikola-breznjak.com\/blog\/javascript\/how-to-override-a-function-when-creating-a-new-object-in-the-prototypal-inheritance\/","title":{"rendered":"How to override a function when creating a new object in the prototypal inheritance?"},"content":{"rendered":"<p><a href=\"http:\/\/stackoverflow.com\/users\/534755\/nikola\"><img loading=\"lazy\" decoding=\"async\" title=\"profile for Nikola at Stack Overflow, Q&amp;A for professional and enthusiast programmers\" src=\"http:\/\/stackoverflow.com\/users\/flair\/534755.png\" rel=\"lightbox[2255]\" alt=\"profile for Nikola at Stack Overflow, Q&amp;A for professional and enthusiast programmers\" width=\"208\" height=\"58\" \/><\/a><br \/>\nI&#8217;m a big fan of <a href=\"http:\/\/stackoverflow.com\/\">Stack Overflow<\/a> and I tend to contribute regularly (am currently in the <a href=\"http:\/\/stackexchange.com\/leagues\/1\/alltime\/stackoverflow\/2008-07-31\/534755?sort=reputationchange#534755\">top 0.X%<\/a>).\u00a0In this category (<a href=\"http:\/\/www.nikola-breznjak.com\/blog\/category\/stack-overflow\/\">stackoverflow<\/a>)\u00a0of posts, I will be posting my top rated questions and answers. This, btw, is allowed as explained in the meta thread <a href=\"http:\/\/meta.stackoverflow.com\/questions\/266971\/can-i-post-so-questions-and-answers-in-a-personal-blog\/266973\">here<\/a>.<\/p>\n<p>I asked the following question which turned out to be quite a popular one:<\/p>\n<p>From <a href=\"http:\/\/davidshariff.com\/blog\/javascript-inheritance-patterns\/\">this blog post<\/a> we have this example of a prototypal inheritance in JavaScript:<\/p>\n<pre class=\"lang:default decode:true \">var human = {\r\n    name: '',\r\n    gender: '',\r\n    planetOfBirth: 'Earth',\r\n    sayGender: function () {\r\n        alert(this.name + ' says my gender is ' + this.gender);\r\n    },\r\n    sayPlanet: function () {\r\n        alert(this.name + ' was born on ' + this.planetOfBirth);\r\n    }\r\n};\r\n\r\nvar male = Object.create(human, {\r\n    gender: {value: 'Male'}\r\n});\r\n\r\nvar female = Object.create(human, {\r\n    gender: {value: 'Female'}\r\n});\r\n\r\nvar david = Object.create(male, {\r\n    name: {value: 'David'},\r\n    planetOfBirth: {value: 'Mars'}\r\n});\r\n\r\nvar jane = Object.create(female, {\r\n    name: {value: 'Jane'}\r\n});\r\n\r\ndavid.sayGender(); \/\/ David says my gender is Male\r\ndavid.sayPlanet(); \/\/ David was born on Mars\r\n\r\njane.sayGender(); \/\/ Jane says my gender is Female\r\njane.sayPlanet(); \/\/ Jane was born on Earth<\/pre>\n<p>Now, what I&#8217;m wondering is how does one <strong>properly<\/strong> &#8220;override&#8221;, for example, the <code>sayPlanet<\/code> function?<\/p>\n<p>I tried it like this:<\/p>\n<pre class=\"lang:default decode:true\">jane.sayPlanet = function(){\r\n    console.log(\"something different\");\r\n};<\/pre>\n<p>and this works.<\/p>\n<p>However, I also tried it like this:<\/p>\n<pre class=\"lang:default decode:true\">var jane = Object.create(female, {\r\n    name: {value: 'Jane'},\r\n\r\n    sayPlanet: function(){\r\n        console.log(\"something different\");\r\n    }\r\n});<\/pre>\n<p>but I get a type error.<\/p>\n<p>My questions are:<\/p>\n<ul>\n<li>how can I add the <code>sayPlanet<\/code> function inside the <code>Object.create<\/code>?<\/li>\n<li>is this at all &#8220;a good way&#8221; or is there a better (best practice) way?<\/li>\n<\/ul>\n<p><strong>edit:<\/strong> I figured a way how I can add the <code>sayPlanet<\/code> inside the <code>Object.create<\/code>:<\/p>\n<pre class=\"lang:default decode:true \">sayPlanet: {\r\n    value: function(){\r\n        console.log(\"something different\");\r\n    }\r\n}<\/pre>\n<p>However, a second question remains. Also, I would appreciate if someone can explain it in a bit deeper level if this is &#8220;a good way&#8221; to use it like this.<\/p>\n<p><strong>edit #2:<\/strong> As Mahavir pointed below, this is an awful example, because as it turns out you can&#8217;t (<strong>please correct me if I&#8217;m wrong<\/strong>) change the <code>name<\/code> of <code>jane<\/code> once it has been <code>Object.create<\/code>d.<\/p>\n<p><strong>edit #3:<\/strong> (man oh man, this is going to get me in a certain facility where people wear white coats). As @WhiteHat pointed below, indeed you can set a name property to be updatable like this:<\/p>\n<pre class=\"lang:default decode:true \">var jane = Object.create(female, {\r\n    name: {\r\n        value: 'Jane',\r\n        writable: true\r\n    }\r\n});<\/pre>\n<p>and then you can do <code>jane.name=\"Jane v2.0\";<\/code>.<\/p>\n<p>I&#8217;ll be honest here people &#8211; I do not have a clue as to which direction to take with seemingly so many options. And just today I read Eric Elliot <a href=\"https:\/\/medium.com\/javascript-scene\/the-two-pillars-of-javascript-ee6f3281e7f3\">https:\/\/medium.com\/javascript-scene\/the-two-pillars-of-javascript-ee6f3281e7f3<\/a> and now I don&#8217;t know what to think anymore because he goes on to argue that people at the ES6 aren&#8217;t quite doing it right :O. Meh, I guess I&#8217;ll have to revisit the Crockfords book yet again, decide on a &#8220;one way&#8221; and see how far it takes me.<\/p>\n<p>&nbsp;<\/p>\n<p>I got quite a few answers, and I also set up a bounty since my question at first didn&#8217;t get much attention. Finally the answer\u00a0by user <a href=\"http:\/\/stackoverflow.com\/users\/4867993\/julien-gr%c3%a9goire\">Julien Gr\u00e9goire<\/a>\u00a0which I accepted was <a href=\"http:\/\/stackoverflow.com\/a\/32922324\/534755\">this one<\/a>:<\/p>\n<blockquote><p>Using <code>Object.create<\/code> is certainly a valid approach, but the example itself seems to me a bit misleading regarding the inner workings of <code>Object.create<\/code>. The blog post does a really good job of summarizing the different ways to create objects in javascript, but I don&#8217;t think the example for <code>Object.create<\/code> gives a good idea of how it works, which is more similar to the <code>new\/constructor<\/code>approach than it may seem.<\/p>\n<p><code>Object.create<\/code> allows to create an object based on a <code>prototype<\/code>, but without a <code>constructor<\/code>. This means that the <code>prototype chain<\/code> of the created object isn&#8217;t dependent on a <code>constructor<\/code>, (which is why it may be simpler to follow, this prototype linked via the constructor is not very straightforward or easy to follow). But <code>Object.create<\/code> still creates a <code>prototype chain<\/code>, in the same way <code>new<\/code> does.<\/p>\n<p>So in your example, when you define <code>name<\/code> in <code>human<\/code> for example here:<\/p>\n<pre class=\"lang:default decode:true\">var human = {\r\n    name: '',<\/pre>\n<p>And then when you create <code>jane<\/code>:<\/p>\n<pre class=\"lang:default decode:true\">var jane = Object.create(female, {\r\n    name: {value: 'Jane'}<\/pre>\n<p>You&#8217;re not really assigning a value to the <code>name property<\/code> you defined in <code>human<\/code>. You&#8217;re in fact adding a property to jane. But <code>human.name<\/code> still is a property in <code>prototype chain<\/code> of <code>jane<\/code>. It works because javascript will follow the prototype chain to find the first matching property, but <code>human.name<\/code> is still somehow linked to <code>jane<\/code>.<\/p>\n<p>See here: <a href=\"https:\/\/developer.mozilla.org\/en-US\/docs\/Web\/JavaScript\/Inheritance_and_the_prototype_chain\" rel=\"nofollow\">https:\/\/developer.mozilla.org\/en-US\/docs\/Web\/JavaScript\/Inheritance_and_the_prototype_chain<\/a><\/p>\n<p>Same thing happens if you use a constructor:<\/p>\n<pre class=\"lang:default decode:true\">var Person = function(gender, name) {\r\n     this.name = name;\r\n}\r\n\r\nvar newPerson = new Person();<\/pre>\n<p>And same goes for <code>sayPlanet<\/code> function.<\/p>\n<p>It&#8217;s a valid approach, but can lead to strange behaviors. For example, you could decide to modifiy <code>sayPlanet<\/code> for all humans by assigning it this way:<\/p>\n<pre class=\"lang:default decode:true\">human.sayPlanet = function(){console.log('new sayPlanet')}<\/pre>\n<p>This would then work for all <code>humans<\/code>, except the ones for which you have given a <code>sayPlanet<\/code>property of their own. Which in your case may be the expected result. But still, you have to see if <code>sayPlanet<\/code> really should be a property of human.<\/p>\n<p>With <code>gender<\/code>, it&#8217;s applied in <code>human<\/code>, and in <code>male<\/code> and <code>female<\/code>. So changing <code>human.gender<\/code> wouldn&#8217;t work on any one. But it&#8217;s still a property of <code>human<\/code>, which is a bit confusing when you want to work with these objects. You basically have a property that is defined, that is writable, but that when changed has no effect at all. It&#8217;s mainly an indication as to which property you need to add to your humans instances or somewhere in the prototype chain. Again, it seems to be used a lot, but when explained with this kind of examples, it somehow gives the impression that <code>Object.create<\/code> just combines properties, but it&#8217;s not what it does.<\/p>\n<p>In the end, you need to chose if you want to work with <code>prototypes<\/code> or not. If not, then Functional inheritance is probably the best way. Then each object is different and has its own set of properties, that you can initialize, and you don&#8217;t have to worry about <code>prototypes<\/code>.<\/p>\n<p>If you want to use <code>prototypes<\/code>, then you can use <code>new\/constructor<\/code> or <code>Object.create<\/code> approach. But <code>Object.create<\/code> will create a prototype chain the same way <code>new<\/code> does, it just gets rid of the constructors.<\/p>\n<p>A small example of how <code>Object.create<\/code> and <code>new<\/code> share some behaviors:<\/p>\n<pre class=\"lang:default decode:true \">var human = {\r\n    name: '',\r\n    gender: '',\r\n    planetOfBirth: 'Earth',\r\n    sayGender: function () {\r\n        console.log(this.name + ' says my gender is ' + this.gender);\r\n    },\r\n    sayPlanet: function () {\r\n        console.log(this.name + ' was born on ' + this.planetOfBirth);\r\n    }\r\n};\r\n\r\nvar male = Object.create(human, {\r\n    gender: {value: 'Male'}\r\n});\r\n\r\nvar female = Object.create(human, {\r\n    gender: {value: 'Female'}\r\n});\r\n\r\n\r\nvar david = Object.create(male, {\r\n    name: {value: 'David'},\r\n    planetOfBirth: {value: 'Mars', configurable: true}\r\n});\r\n\r\nvar jane = Object.create(female, {\r\n    name: {value: 'Jane'},\r\n    sayPlanet: {value: function(){\r\n        console.log(\"something different\");\r\n        }, writable: true, enumerable: true, configurable: true\r\n    }\r\n});\r\n\r\nvar Male = function(name){ \/\/ in this case the real constructor is female or male. Name is the only property that 'needs' to be initialized\r\n    this.name = name;\r\n    this.planetOfBirth = 'Jupiter';\r\n}\r\n\r\nMale.prototype = Object.create(male);\r\n\r\nvar john = new Male('John')\r\n\r\ndavid.sayGender(); \/\/ David says my gender is Male\r\ndavid.sayPlanet(); \/\/ David was born on Mars\r\n\r\njane.sayGender(); \/\/ Jane says my gender is Female\r\njane.sayPlanet(); \/\/ Jane was born on Earth\r\n\r\njohn.sayGender(); \/\/ John says my gender is Female\r\njohn.sayPlanet(); \/\/ John was born on Earth\r\n\r\n\r\ndelete david.planetOfBirth; \/\/just to show how human properties will still be in the chain even if you delete them\r\ndelete john.name; \/\/ It's true also if you use new. \r\ndelete jane.sayPlanet;\r\n\r\nconsole.log('\\n','----after deleting properties----');\r\n\r\ndavid.sayPlanet();\r\njane.sayPlanet();\r\njohn.sayGender();\r\n\r\nhuman.planetOfBirth = 'Venus'; \/\/ This will apply to all humans, even the ones already created\r\n                             \r\nconsole.log('\\n','----after assigning planetOfBirth on human----');\r\n\r\ndavid.sayPlanet();\r\njane.sayPlanet();\r\njohn.sayPlanet(); \/\/ John still has planetOfBirth as its own property, since it wasn't deleted\r\n\r\ndelete john.planetOfBirth;\r\n\r\nconsole.log('\\n','----after deleting john planetOfBirth----');\r\n\r\njohn.sayPlanet();  \/\/ But it's still there<\/pre>\n<p>And in fact (just to be more confusing), some people combine <code>Object.create<\/code> with <code>new\/constructor<\/code>or with Functional inheritance. Something like this for example:<\/p>\n<p><a href=\"https:\/\/john-dugan.com\/object-oriented-javascript-pattern-comparison\/#oloo-pattern\" rel=\"nofollow\">https:\/\/john-dugan.com\/object-oriented-javascript-pattern-comparison\/#oloo-pattern<\/a><\/p>\n<p>Applied to your example it would give something like this:<\/p>\n<pre class=\"lang:default decode:true \">var human = {\r\n    planetOfBirth: 'Earth',\r\n    sayGender: function () {\r\n        console.log(this.name + ' says my gender is ' + this.gender);\r\n    },\r\n    sayPlanet: function () {\r\n              console.log(this.name + ' was born on ' + this.planetOfBirth); \r\n    },\r\n    init: function(name){\r\n        this.name = name;\r\n    }\r\n};\r\n\r\nvar male = Object.create(human, {\r\n    gender: {value: 'Male'} \/\/ This is part of male\/female prototype and can't be written, which seems logical\r\n   });\r\n\r\nvar female = Object.create(human, {\r\n    gender: {value: 'Female'}\r\n});\r\n\r\n\r\nvar david = Object.create(male).init('David');\r\ndavid.planetOfBirth = 'Mars';\r\n\r\nvar jane =  Object.create(female).init('Jane')\r\njane.sayPlanet = function(){console.log('something different')};\r\n\r\nvar john =  Object.create(male).init('John');\r\njohn.planetOfBirth = 'Jupiter';\r\n\r\n\r\n\r\n\r\ndavid.sayGender(); \/\/ David says my gender is Male\r\ndavid.sayPlanet(); \/\/ David was born on Mars\r\n\r\njane.sayGender(); \/\/ Jane says my gender is Female\r\njane.sayPlanet(); \/\/ Jane was born on Earth\r\n\r\njohn.sayGender(); \/\/ John says my gender is Female\r\njohn.sayPlanet(); \/\/ John was born on Earth\r\n\r\n\r\ndelete david.planetOfBirth; \/\/ Overridden properties will still exists after delete, but not the others.\r\ndelete john.name;\r\ndelete jane.sayPlanet;\r\n\r\nconsole.log('\\n','----after deleting properties----');\r\n\r\ndavid.sayPlanet(); \r\njane.sayPlanet(); \r\njohn.sayPlanet(); \r\n\r\nhuman.planetOfBirth = 'Venus'; \/\/ This will apply to all humans, even the ones already created. \r\n                               \/\/ But not for humans woth overridden planetOfBirth.\r\n\r\nconsole.log('\\n','----after assigning planetOfBirth on human----');\r\n\r\ndavid.sayPlanet();\r\njane.sayPlanet();\r\njohn.sayPlanet(); \/\/ John's name is now undefinded\r\n\r\ndelete john.planetOfBirth;\r\n\r\nconsole.log('\\n','----after deleting john planetOfBirth----');\r\n\r\njohn.sayPlanet();  \/\/<\/pre>\n<p>Not necessarily better, but it works as well, and in my opinion has certain advantages.<\/p>\n<p>In any case, as others said, there doesn&#8217;t seem to be a standard or default way to do this.<\/p><\/blockquote>\n<p>Also, another great answer was by a user <a href=\"http:\/\/stackoverflow.com\/users\/2336595\/nice-guy\">Nice-Guy<\/a>:<\/p>\n<blockquote><p>The best practice as I&#8217;ve learned is to define write permissions at the Object prototype level. I learned this technique from reading Addy Osmani&#8217;s JavaScript Design Patterns, it&#8217;s very reputable and open source online: <a href=\"http:\/\/addyosmani.com\/resources\/essentialjsdesignpatterns\/book\/\" rel=\"nofollow\">http:\/\/addyosmani.com\/resources\/essentialjsdesignpatterns\/book\/<\/a><\/p>\n<p>Please check out the sayPlanet property in the example below. Keep in mind, you do not need to set all the other properties&#8217; &#8220;writeable&#8221; to false, I only did it in my example code to illustrate the point. This approach affords more flexibility and reusability than the other, still valid, approaches. Here, you may notice that this is the <code>Object.defineProperties<\/code> syntax within the prototype.<\/p>\n<pre class=\"lang:default decode:true \">var human = {\r\n  name: {\r\n    value: '',\r\n    writable: false \/\/only to illustrate default behavior not needed\r\n  },\r\n  gender: {\r\n    value: '',\r\n    writable: false \/\/only to illustrate default behavior not needed\r\n  },\r\n  planetOfBirth: {\r\n    value: \"Earth\",\r\n    configurable: false \/\/only to illustrate default behavior not needed\r\n  }\r\n\r\n};\r\n\r\n\/\/here we define function properties at prototype level\r\n\r\nObject.defineProperty(human, 'sayGender', {\r\n  value: function() {\r\n    alert(this.name + ' says my gender is ' + this.gender);\r\n  },\r\n  writable: false\r\n});\r\n\r\nObject.defineProperty(human, 'sayPlanet', {\r\n  value: function() {\r\n    alert(this.name + ' was born on ' + this.planetOfBirth);\r\n  },\r\n  writable: true\r\n});\r\n\r\n\/\/end definition of function properties\r\n\r\nvar male = Object.create(human, {\r\n  gender: {\r\n    value: 'Male'\r\n  }\r\n});\r\n\r\nvar female = Object.create(human, {\r\n  gender: {\r\n    value: 'Female'\r\n  }\r\n});\r\n\r\nvar david = Object.create(male, {\r\n  name: {\r\n    value: 'David'\r\n  },\r\n  planetOfBirth: {\r\n    value: 'Mars'\r\n  }\r\n});\r\n\r\nvar jane = Object.create(female, {\r\n  name: {\r\n    value: 'Jane'\r\n  }\r\n});\r\n\r\n\/\/define the writable sayPlanet function for Jane\r\njane.sayPlanet = function() {\r\n  alert(\"something different\");\r\n};\r\n\r\n\/\/test cases\r\n\r\n\/\/call say gender before attempting to ovverride\r\ndavid.sayGender(); \/\/ David says my gender is Male\r\n\r\n\/\/attempt to override the sayGender function for david \r\ndavid.sayGender = function() {\r\n  alert(\"I overrode me!\")\r\n};\r\n\/\/I tried and failed to change an unwritable fucntion\r\ndavid.sayGender(); \/\/David maintains that my gender is Male\r\n\r\ndavid.sayPlanet(); \/\/ David was born on Mars\r\n\r\njane.sayGender(); \/\/ Jane says my gender is Female\r\njane.sayPlanet(); \/\/ something different<\/pre>\n<p>https:\/\/twitter.com\/HitmanHR\/status\/653822447385505792<\/p><\/blockquote>\n","protected":false},"excerpt":{"rendered":"<p>I&#8217;m a big fan of Stack Overflow and I tend to contribute regularly (am currently in the top 0.X%).\u00a0In this category (stackoverflow)\u00a0of posts, I will be posting my&hellip;<\/p>\n","protected":false},"author":1,"featured_media":609,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[27,35],"tags":[],"class_list":["post-2255","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-javascript","category-stack-overflow"],"_links":{"self":[{"href":"https:\/\/nikola-breznjak.com\/blog\/wp-json\/wp\/v2\/posts\/2255","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/nikola-breznjak.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/nikola-breznjak.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/nikola-breznjak.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/nikola-breznjak.com\/blog\/wp-json\/wp\/v2\/comments?post=2255"}],"version-history":[{"count":3,"href":"https:\/\/nikola-breznjak.com\/blog\/wp-json\/wp\/v2\/posts\/2255\/revisions"}],"predecessor-version":[{"id":2258,"href":"https:\/\/nikola-breznjak.com\/blog\/wp-json\/wp\/v2\/posts\/2255\/revisions\/2258"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/nikola-breznjak.com\/blog\/wp-json\/wp\/v2\/media\/609"}],"wp:attachment":[{"href":"https:\/\/nikola-breznjak.com\/blog\/wp-json\/wp\/v2\/media?parent=2255"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/nikola-breznjak.com\/blog\/wp-json\/wp\/v2\/categories?post=2255"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/nikola-breznjak.com\/blog\/wp-json\/wp\/v2\/tags?post=2255"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}