有没有办法强制 javascript 元素根据它最初的定义方式重新定义自己?

ezr*_*zra 5 javascript data-binding 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
]);
Run Code Online (Sandbox Code Playgroud)

我在想,如果有一种方法,内部set的功能$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'
Run Code Online (Sandbox Code Playgroud)

我相信这被称为数据绑定,但我不确定如何在不创建无数代理的情况下做到这一点。

Skr*_*rud 3

您所描述的并不是真正的“数据绑定”,而是“按引用传递”。在您的示例中,您希望更新name反映在$this[\'name\']. 只有当您将引用(或指针)传递给变量时,这才可能实现。

\n\n

然而,在这种情况下,变量是 a string,并且 JavaScript 中的字符串是不可变的

\n\n
\n

没有字符串方法更改它们操作的字符串,它们都返回新字符串。原因是字符串是不可变的 \xe2\x80\x93 它们无法更改,我们只能创建新字符串。

\n
\n\n

因此,逐步完成您的示例:

\n\n

这将创建一个名为“Ezra”的新字符串,并分配一个名为 的变量name来引用该字符串。

\n\n
let name = \'Ezra\';\n
Run Code Online (Sandbox Code Playgroud)\n\n

这将创建(或设置)$thiscall中的一个属性\'name\',该属性引用 in 中的字符串name(即\'Ezra\')。

\n\n
$this[\'name\'] = name;\n
Run Code Online (Sandbox Code Playgroud)\n\n

这将创建一个名为 的新字符串\'Bob\'并将其存储在名为 的变量中name。该变量已经存在。这不会改变之前保存在其中的值。相反,name正在更新以指向新的参考。

\n\n
// then :\nname = \'Bob\';\n
Run Code Online (Sandbox Code Playgroud)\n\n

但是,如果您要传递一个对象,您会发现实际上可以改变它。这是因为对象是按引用传递的,您可以更改该引用处的值

\n\n

例如:

\n\n
// Create a new value that stores an object, with a property \'firstName\'\nlet name = { firstName: \'Ezra\' };\n\n// Assign myObject to $this[\'name\']. Now $this[\'name\'] and name both point to the same reference.\n$this[\'name\'] = name;\n\n// Change the value in the object pointed-to by name\nname.firstName = \'Bob\'\n\nconsole.log($this[\'name\'].firstName); // <- This will output \'Bob\'\n
Run Code Online (Sandbox Code Playgroud)\n