Ludwig GUERIN (2018-02-04T16:32:35.000Z)
An HTML attachment was scrubbed...
URL: <http://mail.mozilla.org/pipermail/es-discuss/attachments/20180204/1e07fa43/attachment.html>
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;
  }
};
```