Ludwig GUERIN (2018-02-04T16:32:35.000Z)
ludwig.guerin.98 at gmx.fr (2018-02-04T16:42:33.963Z)
Sometimes, you need to pass a callback as a parameter of a function. Sometimes, you would like to pass in a method as the said parameter but you may encounter the common issue that the this keyword is not bound to the correct context anymore ; therefore you need to bind the correct context. Let's says that you have : - a function `f` which receives a callback - and an object `obj` which has a method `method` which requires the `this` keyword to be bound to `obj` in order to work properly as intended. You will probably call `f` this way : `f(obj.method.bind(obj));` This is perfectly fine but sometimes can lead to a very large amount of extra "effort" for something that should not require that much "effort" and tends to take away a lot of space and clarity : `f(obj.prop.method.bind(obj.prop));` My suggestion to solve this issue would be to use a new notation based around what C++ developers call the *scope resolution operator*, aka `::`. Here are details on how this should work : - `{object}` refers to an object (it can be either `obj`, or `obj.method`, or `obj.prop`, etc...) - `{method}` refers to one of `{object}`'s methods (if `{object}` is `obj` and we have `obj.method` then `{method}` would be `method`) - The "old-fashioned" way would look like `{object}.{method}.bind({object})` - With this suggestion, it would look like `{object}::{method}` One way to implement such a functionality would be to establish a function `autoBindContext` which would guarantee the following properties : - `{object}::{method}` <=> `autoBindContext({object}.{method}, {object})` - Given any function/method `{fn}`(either `f` or `obj.method`), `autoBindContext({fn}, null) === {fn}` - `{object}::{method}` <=> `({object})::{method}` - ```javascript const a = {object}::{method}; const b = {object}::{method}; a==b; //is true a===b; //is true ``` Below is one implementation of `autoBindContext` : ```javascript const autoBindContext = (method, context=null) => { if(typeof method !== "function") throw new TypeError("Can only bind the context of a function/method"); if(context === null) return method; //Do not bind if the context is null if(!(context instanceof Object)) throw new TypeError("Can only bind a function's/method's context to an object"); const self = autoBindContext; if(!self.cache.hasBinding(method, context)) self.cache.addBinding(method, context); return self.cache.getBinding(method, context); } autoBindContext.cache = { /***********************************\ binding: {context, method, bound} \***********************************/ bindings: [], lookForBinding(method, context=null){ return this.bindings.find(binding => { return binding.context === context && binding.method === method; }); }, hasBinding(method, context=null){ return this.lookForBinding(method, context) !== undefined; }, getBound(method, context=null){ if(this.hasBinding(method, context)) return this.lookForBinding(method, context).bound; return null; }, getBinding(method, context=null){ return this.getBound(method, context); }, addBinding(method, context=null){ if(!this.hasBinding(method, context)){ this.bindings.push({ context, method, bound: method.bind(context) }); } return this; } }; ```
ludwig.guerin.98 at gmx.fr (2018-02-04T16:39:13.373Z)
Sometimes, you need to pass a callback as a parameter of a function. Sometimes, you would like to pass in a method as the said parameter but you may encounter the common issue that the this keyword is not bound to the correct context anymore ; therefore you need to bind the correct context. Let's says that you have : - a function `f` which receives a callback - and an object `obj` which has a method `method` which requires the `this` keyword to be bound to `obj` in order to work properly as intended. You will probably call `f` this way : `f(obj.method.bind(obj));` This is perfectly fine but sometimes can lead to a very large amount of extra "effort" for something that should not require that much "effort" and tends to take away a lot of space and clarity : `f(obj.prop.method.bind(obj.prop));` My suggestion to solve this issue would be to use a new notation based around what C++ developers call the *scope resolution operator*, aka `::`. Here are details on how this should work : - `{object}` refers to an object (it can be either `obj`, or `obj.method`, or `obj.prop`, etc...) - `{method}` refers to one of `{object}`'s methods (if `{object}` is `obj` and we have `obj.method` then `{method}` would be `method`) - The "old-fashioned" way would look like `{object}.{method}.bind({object})` - With this suggestion, it would look like `{object}::{method}` One way to implement such a functionality would be to establish a function `autoBindContext` which would guarantee the following properties : - `{object}::{method}` <=> `autoBindContext({object}.{method}, {object})` - Given any function/method `{fn}`(either `f` or `obj.method`), `autoBindContext({fn}, null) === {fn}` - `{object}::{method}` <=> `({object})::{method}` - ```javascript const a = {object}::{method}; const b = {object}::{method}; a==b; //is true a===b; //is true ``` Below is one implementation of `autoBindContext` : ```javascript const autoBindContext = (method, context=null) => { if(typeof method !== "function") throw new TypeError("Can only bind the context of a function/method"); if(context === null) return method; //Do not bind if the context is null if(!(context instanceof Object)) throw new TypeError("Can only bind a function's/method's context to an object"); const self = autoBindContext; if(!self.cache.hasBinding(method, context)) self.cache.addBinding(method, context); return self.cache.getBinding(method, context); } autoBindContext.cache = { /***********************************\ binding: {context, method, bound} \***********************************/ bindings: [], lookForBinding(method, context=null){ return this.bindings.find(binding => { return binding.context === context && binding.method === method; }); }, hasBinding(method, context=null){ return this.lookForBinding(method, context) !== undefined; }, getBound(method, context=null){ if(this.hasBinding(method, context)) return this.lookForBinding(method, context).bound; return null; }, getBinding(method, context=null){ return this.getBound(method, context); }, addBinding(method, context=null){ if(!this.hasBinding(method, context)){ this.bindings.push({ context, method, bound: method.bind(context) }); } return this; } }; ```
ludwig.guerin.98 at gmx.fr (2018-02-04T16:38:46.299Z)
Sometimes, you need to pass a callback as a parameter of a function. Sometimes, you would like to pass in a method as the said parameter but you may encounter the common issue that the this keyword is not bound to the correct context anymore ; therefore you need to bind the correct context. Let's says that you have : - a function `f` which receives a callback - and an object `obj` which has a method `method` which requires the `this` keyword to be bound to `obj` in order to work properly as intended. You will probably call f this way : `f(obj.method.bind(obj));` This is perfectly fine but sometimes can lead to a very large amount of extra "effort" for something that should not require that much "effort" and tends to take away a lot of space and clarity : `f(obj.prop.method.bind(obj.prop));` My suggestion to solve this issue would be to use a new notation based around what C++ developers call the *scope resolution operator*, aka `::`. Here are details on how this should work : - `{object}` refers to an object (it can be either `obj`, or `obj.method`, or `obj.prop`, etc...) - `{method}` refers to one of `{object}`'s methods (if `{object}` is `obj` and we have `obj.method` then `{method}` would be `method`) - The "old-fashioned" way would look like `{object}.{method}.bind({object})` - With this suggestion, it would look like `{object}::{method}` One way to implement such a functionality would be to establish a function `autoBindContext` which would guarantee the following properties : - `{object}::{method}` <=> `autoBindContext({object}.{method}, {object})` - Given any function/method `{fn}`(either `f` or `obj.method`), `autoBindContext({fn}, null) === {fn}` - `{object}::{method}` <=> `({object})::{method}` - ```javascript const a = {object}::{method}; const b = {object}::{method}; a==b; //is true a===b; //is true ``` Below is one implementation of `autoBindContext` : ```javascript const autoBindContext = (method, context=null) => { if(typeof method !== "function") throw new TypeError("Can only bind the context of a function/method"); if(context === null) return method; //Do not bind if the context is null if(!(context instanceof Object)) throw new TypeError("Can only bind a function's/method's context to an object"); const self = autoBindContext; if(!self.cache.hasBinding(method, context)) self.cache.addBinding(method, context); return self.cache.getBinding(method, context); } autoBindContext.cache = { /***********************************\ binding: {context, method, bound} \***********************************/ bindings: [], lookForBinding(method, context=null){ return this.bindings.find(binding => { return binding.context === context && binding.method === method; }); }, hasBinding(method, context=null){ return this.lookForBinding(method, context) !== undefined; }, getBound(method, context=null){ if(this.hasBinding(method, context)) return this.lookForBinding(method, context).bound; return null; }, getBinding(method, context=null){ return this.getBound(method, context); }, addBinding(method, context=null){ if(!this.hasBinding(method, context)){ this.bindings.push({ context, method, bound: method.bind(context) }); } return this; } }; ```
ludwig.guerin.98 at gmx.fr (2018-02-04T16:38:21.437Z)
Sometimes, you need to pass a callback as a parameter of a function. Sometimes, you would like to pass in a method as the said parameter but you may encounter the common issue that the this keyword is not bound to the correct context anymore ; therefore you need to bind the correct context. Let's says that you have : - a function `f` which receives a callback - and an object `obj` which has a method `method` which requires the `this` keyword to be bound to `obj` in order to work properly as intended. You will probably call f this way : `f(obj.method.bind(obj));` This is perfectly fine but sometimes can lead to a very large amount of extra "effort" for something that should not require that much "effort" and tends to take away a lot of space and clarity : `f(obj.prop.method.bind(obj.prop));` My suggestion to solve this issue would be to use a new notation based around what C++ developers call the *scope resolution operator*, aka `::`. Here are details on how this should work : - `{object}` refers to an object (it can be either `obj`, or `obj.method`, or `obj.prop`, etc...) - `{method}` refers to one of `{object}`'s methods (if `{object}` is `obj` and we have `obj.method` then `{method}` would be `method`) - The "old-fashioned" way would look like `{object}.{method}.bind({object})` - With this suggestion, it would look like `{object}::{method}` One way to implement such a functionality would be to establish a function `autoBindContext` which would guarantee the following properties : - `{object}::{method}` <=> `autoBindContext({object}.{method}, {object})` - Given any function/method `{fn}`(either `f` or `obj.method`), `autoBindContext({fn}, null) === {fn}` - `{object}::{method}` <=> `({object})::{method}` - ```javascript const a = {object}::{method}; const b = {object}::{method}; a==b; //is true a===b; //is true ``` Below is one implementation of `autoBindContext` : ```javascript const autoBindContext = (method, context=null) => { if(typeof method !== "function") throw new TypeError("Can only bind the context of a function/method"); if(context === null) return method; //Do not bind if the context is null if(!(context instanceof Object)) throw new TypeError("Can only bind a function's/method's context to an object"); const self = autoBindContext; if(!self.cache.hasBinding(method, context)) self.cache.addBinding(method, context); return self.cache.getBinding(method, context); } autoBindContext.cache = { /***********************************\ binding: {context, method, bound} \***********************************/ bindings: [], lookForBinding(method, context=null){ return this.bindings.find(binding => { return binding.context === context && binding.method === method; }); }, hasBinding(method, context=null){ return this.lookForBinding(method, context) !== undefined; }, getBound(method, context=null){ if(this.hasBinding(method, context)) return this.lookForBinding(method, context).bound; return null; }, getBinding(method, context=null){ return this.getBound(method, context); }, addBinding(method, context=null){ if(!this.hasBinding(method, context)){ this.bindings.push({ context, method, bound: method.bind(context) }); } return this; } }; ```