是否可以在Javascript中监听原始类型的值变化?

时间:2018-01-17 08:44:55

标签: javascript

假设我想在没有任何框架的情况下实现双向数据绑定。我知道可以通过Object.defineProperty()Proxy等多种方法实现。但是,所有这些方法都需要在obj.a = 'new value'之类的对象的属性上进行更改。是否可以直接观察变量的变化,这样我可以在其他地方调用name = 'new value'时执行我自己的代码?

// A string variable
var name = 'some value';
function nameChanged(newValue) {
    document.getElementById('name').value = newValue;
}
// magic goes here...
...
name = 'new value' // nameChanged() is automatically called.

3 个答案:

答案 0 :(得分:1)

根据您所在的范围(我假设您只是在全球范围内),您可以使用Object.defineProperty并将目标对象设置为window

Object.defineProperty( window, 'name', {
  get() {
    return this._name;
  },
  set(value) {
    if (value === this.name) {
      // didn't change so return
      return;
    }
    var oldValue = this.name;
    this._name = value;
    console.log( `Changed 'name' from ${oldValue} to ${value}` );
  }
});

name = 'test';
name = 'test2';
name = 'test2';
console.log(name);

如果您不在全球范围内,那么这将无效。说实话,我不明白为什么你会强迫它在原始变量上。

如果你想制作自己的观察者版本,你当然可以自己实现像

这样的东西

const createObjectProperty = (context, scope, handleChange) => (property) => {
  Object.defineProperty( context, property, {
    get() {
      return scope[property];
    },
    set( value ) {
      let old = context[property];
      if (old === value) {
        return;
      }
      scope[property] = value;
      handleChange( property, value, old );
    }
  });
};

class Bound {
  constructor( callback, ...props) {
    this.propertyCreator = createObjectProperty(this, {}, this.handlePropertyChanged.bind( this ) );
    if ( callback && !callback.apply ) {
      // probably property
      props = [ callback, ...props ];
    } else {
      this.callback = callback;
    }
    props && props.forEach( this.addProperty.bind( this ) );
  }
  addProperty( property ) {
    this.propertyCreator( property );
  }
  handlePropertyChanged( property, newValue, oldValue ) {
    let { callback } = this;
    callback && callback.apply && callback.apply( this, [property, newValue, oldValue] );
  }
}

var b = new Bound( (property, newValue, oldValue) => {
  console.log( `${property} changed from ${oldValue} to ${newValue}` );
}, 'name', 'lastName' );

b.name = 'test';
b.lastName = 'another test';

console.log( b.name );
console.log( b.lastName );

var b2 = new Bound('test');
b2.test = 'hey joe';
b2.callback = () => { console.log('test changed') };
b2.test = 'hey marie';
console.log( b2.test );
b2.addProperty('name');
b2.name = 'test';

答案 1 :(得分:0)

没有。 Javascript不允许您挂钩该操作。例如,可以在python中使用类似__add__的钩子。但是在python中,你需要构建自己类型的对象(类),然后你就可以决定它发生了什么。

例如,创建一个类Person,然后创建所需的方法,您可以根据自己的意愿进行操作。

class Person {
   constructor(name) {
      this.name = name;
   }

   setName(name) {
      //Whatever it is you wanna do
      this.name = name;
   }
}

答案 2 :(得分:0)

您可以将变量定义为函数,并在调用函数时执行任务

const NAME = 123;
const _name = (value = NAME) => {
                if (value !== NAME) {
                  // do stuff
                }; 
                return value
              };