Skip to content

JS Proxy


js
function createSecureObject(userRole) {
  const data = {
    publicInfo: "This is public information",
    sensitiveInfo: "This is sensitive information (admin only)"
  };

  return new Proxy(data, {
    get(target, property) {
      if (userRole === "admin" || property === "publicInfo") {
        return target[property];
      } else {
        throw new Error(`Unauthorized access to ${property}`);
      }
    },
    set(target, property, value) {
      if (userRole === "admin") {
        target[property] = value;
      } else {
        throw new Error(`Unauthorized modification of ${property}`);
      }
    }
  });
}

const userObject = createSecureObject("user");
const adminObject = createSecureObject("admin");

console.log(userObject.publicInfo); // This is public information
try {
  console.log(userObject.sensitiveInfo); // Error: Unauthorized access to sensitiveInfo
} catch (error) {
  console.error(error.message);
}

try {
  userObject.sensitiveInfo = "Changed"; // Error: Unauthorized modification of sensitiveInfo
} catch (error) {
  console.error(error.message);
}

console.log(adminObject.publicInfo); // This is public information
console.log(adminObject.sensitiveInfo); // This is sensitive information (admin only)
adminObject.sensitiveInfo = "Modified by admin"; // Allowed for admin
console.log(adminObject.sensitiveInfo); // Modified by admin
js
function createCache(initialData = {}) {
  const cache = { ...initialData };

  return new Proxy(cache, {
    get(target, property) {
      if (property in target) {
        console.log(`Getting ${property} from cache`);
        return target[property];
      } else {
        console.log(`${property} not found in cache`);
        return undefined;
      }
    },
    set(target, property, value) {
      console.log(`Setting ${property} in cache`);
      target[property] = value;
      return true;
    }
  });
}

// Simulate loading initial data from localStorage
const initialDataFromStorage = JSON.parse(localStorage.getItem('cachedData')) || {};
const cachedData = createCache(initialDataFromStorage);

cachedData.name = 'John';
cachedData.age = 30;

// Store cached data in localStorage
localStorage.setItem('cachedData', JSON.stringify(cachedData));

console.log(cachedData.name); // This will get the name property from cache
console.log(cachedData.age);  // This will get the age property from cache
console.log(cachedData.email); // This will log that email is not found in cache
js
function createArgumentValidator(targetFunction, argumentTypes) {
  return new Proxy(targetFunction, {
    apply(target, thisArg, argumentsList) {
      if (argumentsList.length !== argumentTypes.length) {
        throw new Error(`Expected ${argumentTypes.length} arguments, but received ${argumentsList.length}`);
      }

      for (let i = 0; i < argumentTypes.length; i++) {
        const expectedType = argumentTypes[i];
        const actualType = typeof argumentsList[i];
        if (actualType !== expectedType) {
          throw new Error(`Argument ${i + 1} should be of type ${expectedType}, but got ${actualType}`);
        }
      }

      return target.apply(thisArg, argumentsList);
    }
  });
}

// Original function
function addNumbers(a, b) {
  return a + b;
}

// Create a validated version of the function
const validatedAdd = createArgumentValidator(addNumbers, ['number', 'number']);

console.log(validatedAdd(2, 3)); // Outputs: 5
try {
  console.log(validatedAdd(2, '3')); // Throws an error due to invalid argument type
} catch (error) {
  console.error(error.message);
}
js
function createImmutableProxy(obj) {
  return new Proxy(obj, {
    set(target, property, value) {
      throw new Error(`Cannot modify "${property}" - Object is immutable`);
    },
    deleteProperty(target, property) {
      throw new Error(`Cannot delete "${property}" - Object is immutable`);
    }
  });
}

const originalPerson = {
  name: 'Alice',
  age: 28,
  address: {
    city: 'Wonderland',
    country: 'Fairyland'
  }
};

const immutablePerson = createImmutableProxy(originalPerson);

console.log('Original Person:', originalPerson);

try {
  immutablePerson.age = 29; // This will throw an error
} catch (error) {
  console.error(error.message);
}

try {
  delete immutablePerson.address; // This will throw an error
} catch (error) {
  console.error(error.message);
}
js
function createValidator(schema) {
  return new Proxy({}, {
    set(target, property, value) {
      const type = schema[property];
      if (typeof type === 'string' && typeof value !== type) {
        throw new TypeError(`${property} must be of type ${type}`);
      }
      target[property] = value;
      return true;
    }
  });
}

// Define a schema for type validation
const schema = {
  name: 'string',
  age: 'number',
  email: 'string'
};

// Create a validated object
const validatedPerson = createValidator(schema);

try {
  validatedPerson.name = 'John';
  validatedPerson.age = 30;
  validatedPerson.email = '[email protected]';

  validatedPerson.age = 'thirty'; // This will throw a TypeError
} catch (error) {
  console.error(error.message);
}
js
function createVirtualization(targetObject, virtualProperties) {
  return new Proxy(targetObject, {
    get(target, property) {
      if (property in virtualProperties) {
        return virtualProperties[property](target[prop], target);
      } else if (property in target) {
        return target[property];
      } else {
        throw new Error(`Property ${property} not found`);
      }
    }
  });
}

const realObject = {
  name: 'Alice',
  age: 30
};

const virtualizedObject = createVirtualization(realObject, {
  fullName: (_, obj) => `${obj.name} Smith`,
  description: (_, obj) => `This is ${obj.name}, aged ${obj.age}`,
  name: value => `My name is ${value}`
});

console.log(virtualizedObject.fullName); // Outputs: Alice Smith
console.log(virtualizedObject.description); // Outputs: This is Alice, aged 30
console.log(virtualizedObject.age); // Outputs: 30 (from the realObject)
console.log(virtualizedObject.unknownProperty); // Throws an error - Property not found
js
const validator = {
  set(target, property, value) {
    if (property === 'age' && typeof value !== 'number') {
      throw new TypeError('Age must be a number');
    }
    target[property] = value;
    return true;
  }
};

const person = new Proxy({}, validator);

person.age = 25; // This will set the age property
person.age = 'twenty-five'; // This will throw a TypeError