Created
          April 19, 2019 18:17 
        
      - 
      
- 
        Save nopjia/cf01468946c7fc7fee1de3a7d4d25e5d to your computer and use it in GitHub Desktop. 
    Creates a new object that watches for changes on its properties
  
        
  
    
      This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
      Learn more about bidirectional Unicode characters
    
  
  
    
  | /** | |
| * Callback whenever a property in the object changes | |
| * @callback onChangeCallback | |
| * @param {*} newValue | |
| * @param {*} oldValue | |
| * @param {String} path | |
| */ | |
| /** | |
| * Creates a new object that is watched for changes | |
| * Works recursively as long as children are objects | |
| * Will not work for newly defined properties | |
| * | |
| * NOTE: Returning a new object instead of modifying | |
| * orignal boosts performance by over 20x | |
| * | |
| * @param {Object} obj | |
| * @param {onChangeCallback} callback | |
| * @return {Object} | |
| */ | |
| const onChange = (obj, callback, pathPrefix = "") => { | |
| const newObj = {}; | |
| const privateData = {}; | |
| const keys = Object.keys(obj); | |
| for (let i = 0; i < keys.length; ++i) { | |
| const key = keys[i]; | |
| let value = obj[key]; | |
| if (typeof value === "object") { | |
| value = onChange(value, callback, `${key}.`); | |
| } | |
| // save key to privateData | |
| privateData[key] = value; | |
| // replace key with getter/setter pointing to privateData | |
| Object.defineProperty(newObj, key, { | |
| enumerable: true, | |
| get() { | |
| return privateData[key]; | |
| }, | |
| set(newValue) { | |
| const oldValue = privateData[key]; | |
| privateData[key] = newValue; | |
| callback(newValue, oldValue, pathPrefix + key); | |
| }, | |
| }); | |
| } | |
| return newObj; | |
| }; | |
| export default onChange; | 
  
    Sign up for free
    to join this conversation on GitHub.
    Already have an account?
    Sign in to comment