2

I need to implemennt data binding or any other kind of variable observer, whenever the variable changes, trigger some defined action. We are also talking about pure JS, I do not want to use any kind of framework or library due to the performance issues.

I have found a pretty simple and nice data binding code, but its behavior is quite wierd. It works only if you try to bind only 1 variable. Whenever you try to bind multiple variables, it will bind all actions to the last element, even if the bindings was called separately to different variables.

function Binding(b) {
 _this = this
 this.element = b.element
 this.value = b.object[b.property]
 this.attribute = b.attribute
 this.valueGetter = function(){
  return _this.value;
 }
 this.valueSetter = function(val){
  _this.value = val
  _this.element[_this.attribute] = val
 }

 Object.defineProperty(b.object, b.property, {
  get: this.valueGetter,
  set: this.valueSetter
 }); 
 b.object[b.property] = this.value;
 
 this.element[this.attribute] = this.value
}


var obj = {a:123, b:456, c:789};
var myElement = document.getElementById("myText");
var a = new Binding({
 object: obj,
 property: "a",
 element: document.getElementById("myText"),
 attribute: "value",
});

var b = new Binding({
 object: obj,
 property: "b",
 element: document.getElementById("myText2"),
 attribute: "value",
});

var c = new Binding({
 object: obj,
 property: "c",
 element: document.getElementById("myText3"),
 attribute: "value",
});

setInterval(function(){
for(var key in obj)
{obj[key]++;} }, 1000);
<input type=text id="myText"/>
<input type=text id="myText2"/>
<input type=text id="myText3"/>

Any idea please, how to alter the code in such a way, that I can bind the variables separately? I have tried to play with .bind() like if the "this" is overwriting something, I tried to play with rewriting function Bind to class, but so far with no results ...

Any help appreciated, thanks!

Zorak
  • 709
  • 7
  • 24
  • 1
    `_this = this` you are creating an implicit global – VLAZ Sep 04 '19 at 18:41
  • Possible duplicate of [What is the purpose of the var keyword and when should I use it (or omit it)?](https://stackoverflow.com/questions/1470488/what-is-the-purpose-of-the-var-keyword-and-when-should-i-use-it-or-omit-it) – VLAZ Sep 04 '19 at 18:41

1 Answers1

1

Just use arrow functions to avoid redefining "this" and to avoid having to hack around it with a global variable:

function Binding(b) {
    this.element = b.element
    this.value = b.object[b.property]
    this.attribute = b.attribute
    this.valueGetter = () => {
        return this.value;
    }
    this.valueSetter = (val) => {
        this.value = val
        this.element[_this.attribute] = val
    }

    Object.defineProperty(b.object, b.property, {
        get: this.valueGetter,
        set: this.valueSetter
    }); 
    b.object[b.property] = this.value;

    this.element[this.attribute] = this.value
}

You could also use const, let, or var when defining _this, as a patch on top of your _this hack. But arrow functions avoid the _this hack in the first place. They're designed to avoid the scoping issues that led to the _this hack.

Andrew Koster
  • 1,550
  • 1
  • 21
  • 31
  • Worth noting: Arrow functions are not supported in `Internet Explorer` or `Opera Mini` – Riddell Sep 04 '19 at 18:54
  • @Riddell Opera *Mini*. Opera itself supported arrow functions pretty much since ES6 came out. It's running on Chromium, so it's hard to not be up to date with web standards there. – VLAZ Sep 04 '19 at 18:57
  • Opera has supported arrow functions since 2015. But yes, if you need to support every browser on every device, you might need to set up an ES6 to ES5 compilation step to support modern Javascript syntax. – Andrew Koster Sep 04 '19 at 18:57
  • Yes sorry, I was on two questions at once. That was typo. I've updated the comment – Riddell Sep 04 '19 at 18:57
  • This sounds like it's a new project, so it's probably best to avoid starting the project with the technical debt of archaic Javascript syntax, especially for something fundamental like the data binding API. – Andrew Koster Sep 04 '19 at 18:59
  • Based on your suggestion and also the comment of @VLAZ, now it is working correctly, I just removed the ecma6 arrow functions and replaced them by standard function declaration, and it is now working, when I also removed "this" and just created var t = {}; as holder for all inner data. Many thanks, this is working :) – Zorak Sep 04 '19 at 19:05