Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is there a way to force a javascript element to redefine itself based on how it was originally defined?

I was playing around with objects and constructors and stuff like that, and I was wondering if there was a way to bind a value to a variable based on how it was originally defined. I have the following code:

typescript

let cr = "create",
  ap = "apply",
  $this = {
    set: (prop, value) => {
      this[prop] = value;
    }
  };
function creator() {
  this.$ = (array: Object[]) => {
    array.forEach((kp: Object) => {
      let key = Object.keys(kp)[0];
      let val = kp[Object.keys(kp)];
      $this[key] = val;
      creator.create(key, { value: val });
    });
  };
  this.apply = (...objects: Object[]) => {
    objects.forEach((obj: Object) => {
      creator.call(obj);
    });
  };
}
function create(obj) {
  function createValues(arr) {
    let instance: Object = new obj();
    let vals: any[] = [];
    arr.forEach(name => {
      vals.push(instance[name]);
    });
    return vals;
  }
  let names: string[] = Object.getOwnPropertyNames(new obj());
  let values: string[] = createValues(names);
  return combineArrays(names, values);
}
function combineArrays(arr1, arr2): { $?: any } { // the question mark removes an IDE error
  let newObj: Object = {};
  arr1.forEach(prop => {
    newObj[prop] = arr2[arr1.indexOf(prop)];
  });
  return newObj;
}
Object.prototype.create = function(prop, options) {
  return Object.defineProperty(this, prop, options);
};
create(creator).$([
  { hi: "hi" }, 
  { bye: $this["hi"] } // this is the important stuff
]);

I was wondering if there is a way, inside the set function of the $this variable, to detect how it is being set and therefore determine if that value has changed and so it's value should to, if that makes any sense? Let's say you had this:

let $this = {
  set: function(prop, value) {
    this[prop] = value;
  } 
}
let name = 'Ezra';
$this['name'] = name;
// then :
name = 'Bob';
// change $this.name too, so then:
console.log($this.name);
// >> 'Bob'

I believe this is called Data-Binding but I am unsure how to do it without creating endless numbers of proxies.

like image 968
ezra Avatar asked Oct 15 '22 07:10

ezra


1 Answers

What you're describing is not really "data-binding" but pass-by-reference. In your example you expect an update to name to be reflected in $this['name']. That would only be possible if you were passing a reference (or a pointer) to the variable.

However, in this case the variable is a string, and strings in JavaScript are immutable:

no string methods change the string they operate on, they all return new strings. The reason is that strings are immutable – they cannot change, we can only ever make new strings.

So, going step-by-step through your example:

This creates a new string named 'Ezra', and assigns a variable called name to reference that string.

let name = 'Ezra';

This creates (or sets) a property in $this called 'name' that references the string in name (which is 'Ezra').

$this['name'] = name;

This creates a new string called 'Bob' and stores it in the variable called name. The variable already exists. This does not mutate the value that was previously held in there. Instead, name is being updated to point to a new reference.

// then :
name = 'Bob';

However, if you were to pass an object, you'll notice that you can actually mutate it. This is because objects are passed-by-reference and you can mutate the value at that reference.

For example:

// Create a new value that stores an object, with a property 'firstName'
let name = { firstName: 'Ezra' };

// Assign myObject to $this['name']. Now $this['name'] and name both point to the same reference.
$this['name'] = name;

// Change the value in the object pointed-to by name
name.firstName = 'Bob'

console.log($this['name'].firstName); // <- This will output 'Bob'
like image 56
Skrud Avatar answered Nov 02 '22 06:11

Skrud