{"id":562,"date":"2018-06-20T10:28:59","date_gmt":"2018-06-19T22:28:59","guid":{"rendered":"https:\/\/content.ronella.xyz\/apps\/wordpress\/?p=562"},"modified":"2018-06-20T10:28:59","modified_gmt":"2018-06-19T22:28:59","slug":"javascript-prototypal-inheritance","status":"publish","type":"post","link":"https:\/\/www.ronella.xyz\/?p=562","title":{"rendered":"JavaScript Prototypal Inheritance"},"content":{"rendered":"<p>The JavaScript's facility to provide inheritance is via<strong> prototype property of the constructor function<\/strong>\u00a0<em>(i.e. accessible via __proto__ in the instance context)<\/em>. Thus, we normally use the prototype to make properties and functions possible to be inherited. See the following code to do the inheritance properly.<\/p>\n<h6>Code 1 - Proper Way of Implementing Prototypal Inheritance<\/h6>\n<pre style=\"white-space: pre;\">\"use strict\";\r\n\r\nfunction Person(firstName, lastName) {\r\n  this.firstName = firstName;\r\n  this.lastName = lastName;\r\n}\r\n\r\nPerson.prototype.middleName = \"\";\r\n\r\nObject.defineProperty(Person.prototype, 'fullName', {\r\n  get: function() {\r\n    var name = (this.firstName||\"\");\r\n    name += (name.length&gt;0 ? \" \" : \"\") + (this.middleName||\"\");\r\n    name += (name.length&gt;0 ? \" \" : \"\") + (this.lastName||\"\");\r\n      return name;\r\n  }, \r\n  set: function(name) {\r\n    var DELIM = \" \";\r\n    var names = (name||\"\").split(DELIM);\r\n    this.firstName = names[0];\r\n    this.lastName = names[1];\r\n  }\r\n});\r\n\r\nfunction Employee(firstName, lastName, position) {\r\n   <strong>Person.call(this, firstName, lastName)<\/strong>;\r\n   this.position = position||\"\";\r\n}\r\n\r\nEmployee.prototype = <strong>Object.create(Person.prototype)<\/strong>;\r\n<strong>Employee.prototype.constructor = Employee<\/strong>;\r\n\r\nvar person = new Person();\r\nperson.fullName = \"Ron Webb\";\r\nconsole.log(person.fullName);\r\n\r\nvar employee = new Employee(\"Ofelia\", \"Webb\", \"Manager\");\r\nconsole.log(employee.fullName);\r\nconsole.log(employee.position);\r\n<\/pre>\n<p>Based on preceding code, the Employee is inheriting the Person via the following snippet:<\/p>\n<h6>Snippet 1 - Inhering the Person Class<\/h6>\n<pre style=\"white-space: pre;\">Employee.prototype = Object.create(Person.prototype);<\/pre>\n<p>But, we should not stop there. We need to also specify the constructor to use the create the instance of Employee like the following snippet:<\/p>\n<h6>Snippet 2 - Specify the Constructor to Create the Employee Instance<\/h6>\n<pre>Employee.prototype.constructor = Employee;<\/pre>\n<p>Lastly, in the constructor implementation of the Employee try to also call the constructor of the Person like the following snippet:<\/p>\n<h6>Snippet 3 - Call the Parent's Constructor<\/h6>\n<pre style=\"white-space: pre;\">function Employee(firstName, lastName, position) {\r\n   <strong>Person.call(this, firstName, lastName);<\/strong>\r\n   this.position = position||\"\";\r\n}<\/pre>\n<h4>Using ES6 Syntactic Sugar for Inheritance<\/h4>\n<p>With ES6, this was greatly simplified because we don't need to deal with the prototype property of the constructor function like the following code:<\/p>\n<h6>Code 2 - ES6 implementation of Code 1<\/h6>\n<pre style=\"white-space: pre;\">\"use strict\";\r\n\r\n<strong>class<\/strong> Person {\r\n  <strong>constructor<\/strong>(firstName, lastName) {\r\n    this.firstName = firstName;\r\n    this.lastName = lastName;\r\n    this.middleName = \"\";\r\n  }\r\n  \r\n  <strong>get<\/strong> fullName() {\r\n    var name = (this.firstName||\"\");\r\n    name += (name.length&gt;0 ? \" \" : \"\") + (this.middleName||\"\");\r\n    name += (name.length&gt;0 ? \" \" : \"\") + (this.lastName||\"\");\r\n      return name;  \r\n  }\r\n  \r\n  <strong>set<\/strong> fullName(name) {\r\n    <strong>const<\/strong> DELIM = \" \";\r\n    var names = (name||\"\").split(DELIM);\r\n    this.firstName = names[0];\r\n    this.lastName = names[1];  \t\r\n  }\r\n}\r\n\r\nclass Employee <strong>extends<\/strong> Person {\r\n  constructor(firstName, lastName, position) {\r\n   <strong>super<\/strong>(firstName, lastName);\r\n    this.position = position||\"\";\r\n  }\r\n}\r\n\r\nvar person = new Person();\r\nperson.fullName = \"Ron Webb\";\r\nconsole.log(person.fullName);\r\n\r\nvar employee = new Employee(\"Ofelia\", \"Webb\", \"Manager\");\r\nconsole.log(employee.fullName);\r\nconsole.log(employee.position);<\/pre>\n<p>In ES6, we can now use the <strong>class keyword<\/strong> to define a class and a <strong>constructor method<\/strong> for its initialization. Regarding the constructor, we can now use the <strong>super method<\/strong> to call the parent constructor.<\/p>\n<p>Moreover, implementing <strong>getter\u00a0<em>(i.e. using the get keyword before the function name)<\/em><\/strong> and <strong>setter\u00a0<em>(i.e. using the set keyword before the function name)<\/em><\/strong> are now very simple. Also the\u00a0<strong>const keyword<\/strong> is now available to define immutable identifier just like what we can see on the fullName setter as we can see in the following snippet:<\/p>\n<h6>Snippet 4 - Using the Const Keyword<\/h6>\n<pre>set fullName(name) {\r\n  <strong>const<\/strong> DELIM = \" \";\r\n  var names = (name||\"\").split(DELIM);\r\n  this.firstName = names[0];\r\n  this.lastName = names[1];  \t\r\n}<\/pre>\n<p>All these enhancements in ES6 related to inheritance, in the background it still using the <strong>prototypical way<\/strong>. Remember these are just syntactic sugar.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>The JavaScript&#8217;s facility to provide inheritance is via prototype property of the constructor function\u00a0(i.e. accessible via __proto__ in the instance context). Thus, we normally use the prototype to make properties and functions possible to be inherited. See the following code to do the inheritance properly. Code 1 &#8211; Proper Way of Implementing Prototypal Inheritance &#8220;use [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":[],"categories":[38],"tags":[],"_links":{"self":[{"href":"https:\/\/www.ronella.xyz\/index.php?rest_route=\/wp\/v2\/posts\/562"}],"collection":[{"href":"https:\/\/www.ronella.xyz\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.ronella.xyz\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.ronella.xyz\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.ronella.xyz\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=562"}],"version-history":[{"count":24,"href":"https:\/\/www.ronella.xyz\/index.php?rest_route=\/wp\/v2\/posts\/562\/revisions"}],"predecessor-version":[{"id":586,"href":"https:\/\/www.ronella.xyz\/index.php?rest_route=\/wp\/v2\/posts\/562\/revisions\/586"}],"wp:attachment":[{"href":"https:\/\/www.ronella.xyz\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=562"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.ronella.xyz\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=562"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.ronella.xyz\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=562"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}