{"id":38628,"date":"2016-07-29T20:10:21","date_gmt":"2016-07-29T14:40:21","guid":{"rendered":"http:\/\/www.tothenew.com\/blog\/?p=38628"},"modified":"2016-08-11T19:38:54","modified_gmt":"2016-08-11T14:08:54","slug":"future-of-data-binding","status":"publish","type":"post","link":"https:\/\/www.tothenew.com\/blog\/future-of-data-binding\/","title":{"rendered":"Future of Data Binding"},"content":{"rendered":"<p>A new revolution has come. There are few new APIs introduced in <strong>ECMAScript 5<\/strong>, but the most interesting functionality is added to Object property code. This new code gives you the ability to <strong>redefine<\/strong> the <strong>capabilities<\/strong> of an Object property. Capabilities like preventing <strong>Object manipulation, enumeration, deletion and addition<\/strong> of new property and even defining their <strong>getters and setters<\/strong>.<\/p>\n<p>Three plus years back <strong>Rafael Weinstein, Erik Arvidsson and Adam Klein started<\/strong> implementing or we can say started developing the true way of data binding system of <strong>MDV (&#8220;model-driven views&#8221;)<\/strong>. They got an agreement from the <strong>V8<\/strong> team and started implementing <strong>Object.observe (&#8220;O.o&#8221;)<\/strong>. Behind them Polymer team started building their framework system on top of O.o. As of now the world has changed in a variety of ways as other frameworks like <strong>Angular and Ember<\/strong> started their own. It will be interesting to watch how far they will manage to build their frameworks without them.<\/p>\n<p>As <strong>O.o<\/strong> gets postponed from ECMAScript 5 and to be a part of <strong>ECMAScript 7<\/strong> because not all browsers have implemented this functionality yet. A Synonym to that is <strong>Object.watch<\/strong>, which was a part of Firefox for testing purposes. Due to this Polymer rewrote their framework to support all browsers and released their first production version 1.0 without O.o.<\/p>\n<p>Then comes <strong>Object.defineProperty<\/strong> which can create a watch over an Object property.<br \/>\nExample :-<\/p>\n<p>[code language=&#8221;html&#8221;]<br \/>\n&lt;script&gt;<br \/>\nfunction _observe(properties, callback) {<br \/>\n    var _obj = {};<br \/>\n    Object.keys(properties).forEach(function(key) {<br \/>\n        Object.defineProperty(_obj, key, {<br \/>\n            get: function() {<br \/>\n                console.log(&#8216;get!&#8217;);<br \/>\n                return properties[key];<br \/>\n            },<br \/>\n            set: function(value) {<br \/>\n                callback(key, properties[key], value);<br \/>\n                properties[key] = value;<br \/>\n            }<br \/>\n        });<br \/>\n    });<br \/>\n    return _obj;<br \/>\n}<br \/>\nvar obj = { &quot;firstname&quot;: &quot;himanshu&quot;, &quot;lastName&quot;: &quot;adhikari&quot; };<br \/>\nvar scope = _observe(obj, function(key, oldValue, newValue) {<br \/>\n    console.log(key, oldValue, newValue)<br \/>\n});<br \/>\n&lt;\/script&gt;<br \/>\n[\/code]<\/p>\n<p>Now change scope.firstName and observe console pane<\/p>\n<p>scope.firstName = \u201cRaman\u201d;<\/p>\n<p><strong>Note:<\/strong> Please don\u2019t try to replace <strong>_obj<\/strong> with <strong>properties<\/strong> in Object.defineProperty method as it will make it a recursive call to get function.<\/p>\n<p><strong>Getter and Setters:<\/strong> When Getter and Setters were not present in javascript we need to do a dirty check over an object as to identify which property gets affected after an event finishes it execution or an async call gets completed. This dirty checking or we can say the extra time we are taking in finding whether it&#8217;s an <strong>\u201cupdate\u201d<\/strong>, an <strong>\u201caddition\u201d<\/strong> or a <strong>\u201cdeletion\u201d<\/strong> from an object can be overcome by setting Getters and Setters over object properties.<\/p>\n<p><strong>Enumeration:<\/strong> Now try to run below method, and you\u2019ll find that nothing will appear on browser&#8217;s console.<\/p>\n<p>[code language=&#8221;html&#8221;]<br \/>\nObject.keys(scope).forEach(function(key){<br \/>\n\tconsole.log(key)<br \/>\n});<br \/>\n[\/code]<\/p>\n<p>This is because by default <strong>enumeration<\/strong> is <strong>false<\/strong> and the object property will not show up during property enumeration <strong>(for&#8230;in loop or Object.keys method)<\/strong>. To set it an example is given below:-<\/p>\n<p>[code language=&#8221;html&#8221;]<\/p>\n<p>function _observe(properties, callback) {<br \/>\n    var _obj = {};<br \/>\n    Object.keys(properties).forEach(function(key) {<br \/>\n        Object.defineProperty(_obj, key, {<br \/>\n            get: function() {<br \/>\n                console.log(&#8216;get!&#8217;);<br \/>\n                return properties[key];<br \/>\n            },<br \/>\n            set: function(value) {<br \/>\n                callback(key, properties[key], value);<br \/>\n                properties[key] = value;<br \/>\n            },<br \/>\n            enumerable: true,<br \/>\n        });<br \/>\n    });<br \/>\n    return _obj;<br \/>\n}<br \/>\n[\/code]<\/p>\n<p>Now run for loop over scope variable and this time logs will appear on browser&#8217;s console.<\/p>\n<p><strong>Configurable:<\/strong> Now try to run below code, and you\u2019ll find that deleting a object property was never so tough before.<\/p>\n<p>[code language=&#8221;html&#8221;]<br \/>\ndelete scope.firstName;<br \/>\n[\/code]<\/p>\n<p>This is because by default <strong>configurable<\/strong> is set to <strong>false<\/strong> if not passed to Object.defineProperty. If you want to <strong>enable deletion<\/strong> on an object property then turn it to <strong>true<\/strong>.<\/p>\n<p><strong>Writable:<\/strong> If set to <strong>false<\/strong> then you <strong>cannot change<\/strong> the value of an object property, defaults to false. Writable cannot be used when <strong>getters and setters<\/strong> are present to Object.defineProperty.<\/p>\n<p>[code language=&#8221;html&#8221;]<br \/>\nvar o = {}; \/\/ Creates a new object<\/p>\n<p>\/\/ Example of an object property added with defineProperty with a data property descriptor<br \/>\nObject.defineProperty(o, &#8216;a&#8217;, {<br \/>\n    value: 37,<br \/>\n    writable: true,<br \/>\n    enumerable: true,<br \/>\n    configurable: true<br \/>\n});<br \/>\n[\/code]<\/p>\n<p><strong>Object.defineProperties:<\/strong><br \/>\nThere is one more method which can create a watch over an Object. This method defines <strong>new<\/strong> or <strong>modifies<\/strong> existing properties directly on an object, returning the object.<\/p>\n<p><strong>Syntax:<\/strong><\/p>\n<p>[code language=&#8221;html&#8221;]<br \/>\nObject.defineProperties(obj, properties)<br \/>\n[\/code]<\/p>\n<p><strong>Example:<\/strong><\/p>\n<p>[code language=&#8221;html&#8221;]<br \/>\nvar obj = {};<br \/>\nObject.defineProperties(obj, {<br \/>\n    &quot;firstName&quot;: {<br \/>\n        value: &quot;john&quot;,<br \/>\n        writable: true<br \/>\n    },<br \/>\n    &quot;lastName&quot;: {<br \/>\n        value: &quot;carter&quot;,<br \/>\n        writable: false<br \/>\n    }<br \/>\n});<br \/>\n[\/code]<\/p>\n<p><strong>Object.defineProperty<\/strong> is used when you want to define a <strong>single property<\/strong> directly on an object but if you want to define <strong>multiple<\/strong> properties on an object with different configurations then you can use <strong>Object.defineProperties<\/strong>.<\/p>\n<p>Till now we\u2019ve learnt how to define and modify property\/properties of an Object. Now let&#8217;s learn how we can react on <strong>DOM changes<\/strong>.<\/p>\n<p><strong>Mutation Observers:<\/strong> provides a way to <strong>react to changes in a DOM<\/strong>, changes like <strong>addition<\/strong> and <strong>removal<\/strong> of HTML node on DOM and even more detects changes in HTML node attributes.<\/p>\n<p>Now lets create an example to observe the changes whenever a new attribute is added or being changed. Open your developer tools and go to console pane, now paste the below code.<\/p>\n<p>[code language=&#8221;html&#8221;]<br \/>\n\/\/ select the target node<br \/>\nvar target = document.querySelector(&#8216;body&#8217;);<\/p>\n<p>\/\/ create an observer instance<br \/>\nvar observer = new MutationObserver(function(mutations) {<br \/>\n    mutations.forEach(function(mutation) {<br \/>\n        console.log(mutation);<br \/>\n    });<br \/>\n});<\/p>\n<p>\/\/ configuration of the observer:<br \/>\n\/\/ set attributeOldValue to true if want to get old value of an attribute:<br \/>\nvar config = { attributes: true, attributeOldValue: true };<\/p>\n<p>\/\/ pass in the target node, as well as the observer options<br \/>\nobserver.observe(target, config);<br \/>\n[\/code]<\/p>\n<p>Now go to <strong>element pane<\/strong> in <strong>developer tools<\/strong> and <strong>add<\/strong> any new <strong>attribute with value<\/strong> to body tag. Now press <strong>Esc<\/strong> and observe logs in <strong>console pane<\/strong>. You can see Mutation Records, as what is being changed on the target node. It will only tell us what was the old value of an attribute, you can get the new value from target node by<\/p>\n<p>[code language=&#8221;html&#8221;]<br \/>\ntarget.getAttribute(MutationRecord.attributeName);<\/p>\n<p>\/\/ later, you can stop observing<br \/>\nobserver.disconnect();<br \/>\n[\/code]<\/p>\n<p>Now let&#8217;s observe the <strong>addition\/deletion<\/strong> of nodes in DOM.<\/p>\n<p>[code language=&#8221;html&#8221;]<br \/>\n&lt;ol contenteditable oninput=&quot;&quot;&gt;<br \/>\n  &lt;li&gt;Press enter&lt;\/li&gt;<br \/>\n&lt;\/ol&gt;<\/p>\n<p>&lt;script&gt;<br \/>\nvar MutationObserver = window.MutationObserver || window.WebKitMutationObserver || window.MozMutationObserver;<\/p>\n<p>var list = document.querySelector(&#8216;ol&#8217;);<\/p>\n<p>var observer = new MutationObserver(function(mutations) {<br \/>\n    mutations.forEach(function(mutation) {<br \/>\n        if (mutation.type === &#8216;childList&#8217;) {<br \/>\n            var list_values = [].slice.call(list.children)<br \/>\n                .map(function(node) {<br \/>\n                    return node.innerHTML;<br \/>\n                })<br \/>\n                .filter(function(s) {<br \/>\n                    if (s === &#8216;&lt;br \/&gt;&#8217;) {<br \/>\n                        return false;<br \/>\n                    } else {<br \/>\n                        return true;<br \/>\n                    }<br \/>\n                });<br \/>\n        }<br \/>\n    });<br \/>\n});<\/p>\n<p>observer.observe(list, {<br \/>\n    attributes: true,<br \/>\n    childList: true,<br \/>\n    characterData: true<br \/>\n});<br \/>\n&lt;\/script&gt;<br \/>\n[\/code]<\/p>\n<p>Set <strong>childList<\/strong> to <strong>true<\/strong> if want to observe any addition\/deletion to a particular child nodes.<\/p>\n<p>Now my question is do we still need <strong>dirty checking frameworks<\/strong> if we have a way to <strong>observe and react<\/strong> whenever a change happens on <strong>DOM\/Objects<\/strong> rather than checking every time as what was changed and if the code is not well written then you\u2019ll find that in background something is still executing. As the project increases its size it becomes slow in browsers.<\/p>\n<p>Till now we&#8217;ve learnt how to Observe the changes of an Object and how we can react to DOM manipulation. As the time is changing, there are several changes made to the web to make it smater. Now its time to make yourself smater and use only that much code which is required for making a website. I think every website is different from each other and each website requires their own framework&#8217;s according to their requirements. I request you to try implementing something from what we&#8217;ve discussed today.<\/p>\n<p>Meet you guys soon with my next blog, till then <strong>HAPPY CODING!!!<\/strong><\/p>\n","protected":false},"excerpt":{"rendered":"<p>A new revolution has come. There are few new APIs introduced in ECMAScript 5, but the most interesting functionality is added to Object property code. This new code gives you the ability to redefine the capabilities of an Object property. Capabilities like preventing Object manipulation, enumeration, deletion and addition of new property and even defining [&hellip;]<\/p>\n","protected":false},"author":911,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"iawp_total_views":1},"categories":[1],"tags":[3846,55,3845,3844,3843],"aioseo_notices":[],"_links":{"self":[{"href":"https:\/\/www.tothenew.com\/blog\/wp-json\/wp\/v2\/posts\/38628"}],"collection":[{"href":"https:\/\/www.tothenew.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.tothenew.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.tothenew.com\/blog\/wp-json\/wp\/v2\/users\/911"}],"replies":[{"embeddable":true,"href":"https:\/\/www.tothenew.com\/blog\/wp-json\/wp\/v2\/comments?post=38628"}],"version-history":[{"count":0,"href":"https:\/\/www.tothenew.com\/blog\/wp-json\/wp\/v2\/posts\/38628\/revisions"}],"wp:attachment":[{"href":"https:\/\/www.tothenew.com\/blog\/wp-json\/wp\/v2\/media?parent=38628"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.tothenew.com\/blog\/wp-json\/wp\/v2\/categories?post=38628"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.tothenew.com\/blog\/wp-json\/wp\/v2\/tags?post=38628"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}