ಕನ್ನಡ

ಜಾಗತಿಕ ಡೆವಲಪರ್‌ಗಳಿಗಾಗಿ ಜಾವಾಸ್ಕ್ರಿಪ್ಟ್ ಪ್ರಾಕ್ಸಿ API ಅನ್ನು ಕರಗತ ಮಾಡಿಕೊಳ್ಳಲು ಒಂದು ಸಮಗ್ರ ಮಾರ್ಗದರ್ಶಿ. ಪ್ರಾಯೋಗಿಕ ಉದಾಹರಣೆಗಳು ಮತ್ತು ಬಳಕೆಯ ಸಂದರ್ಭಗಳೊಂದಿಗೆ ಆಬ್ಜೆಕ್ಟ್ ಕಾರ್ಯಾಚರಣೆಗಳನ್ನು ಕಸ್ಟಮೈಸ್ ಮಾಡಲು ಕಲಿಯಿರಿ.

ಜಾವಾಸ್ಕ್ರಿಪ್ಟ್ ಪ್ರಾಕ್ಸಿ API: ಆಬ್ಜೆಕ್ಟ್ ವರ್ತನೆಯ ಮಾರ್ಪಾಡಿನ ಒಂದು ಆಳವಾದ ನೋಟ

ಆಧುನಿಕ ಜಾವಾಸ್ಕ್ರಿಪ್ಟ್‌ನ ವಿಕಸಿಸುತ್ತಿರುವ ಕ್ಷೇತ್ರದಲ್ಲಿ, ಡೆವಲಪರ್‌ಗಳು ಡೇಟಾವನ್ನು ನಿರ್ವಹಿಸಲು ಮತ್ತು ಅದರೊಂದಿಗೆ ಸಂವಹನ ನಡೆಸಲು ಹೆಚ್ಚು ಶಕ್ತಿಶಾಲಿ ಮತ್ತು ಸೊಗಸಾದ ಮಾರ್ಗಗಳನ್ನು ನಿರಂತರವಾಗಿ ಹುಡುಕುತ್ತಿದ್ದಾರೆ. ಕ್ಲಾಸ್‌ಗಳು, ಮಾಡ್ಯೂಲ್‌ಗಳು ಮತ್ತು async/await ನಂತಹ ವೈಶಿಷ್ಟ್ಯಗಳು ನಾವು ಕೋಡ್ ಬರೆಯುವ ವಿಧಾನವನ್ನು ಕ್ರಾಂತಿಗೊಳಿಸಿದ್ದರೂ, ECMAScript 2015 (ES6) ನಲ್ಲಿ ಪರಿಚಯಿಸಲಾದ ಒಂದು ಪ್ರಬಲ ಮೆಟಾಪ್ರೋಗ್ರಾಮಿಂಗ್ ವೈಶಿಷ್ಟ್ಯವಿದೆ, ಅದು ಹೆಚ್ಚಾಗಿ ಬಳಕೆಯಲ್ಲಿಲ್ಲ: ಪ್ರಾಕ್ಸಿ API.

ಮೆಟಾಪ್ರೋಗ್ರಾಮಿಂಗ್ ಎಂಬುದು ಭಯ ಹುಟ್ಟಿಸುವಂತೆ ತೋರಬಹುದು, ಆದರೆ ಇದು ಸರಳವಾಗಿ ಇತರ ಕೋಡ್ ಮೇಲೆ ಕಾರ್ಯನಿರ್ವಹಿಸುವ ಕೋಡ್ ಬರೆಯುವ ಪರಿಕಲ್ಪನೆಯಾಗಿದೆ. ಪ್ರಾಕ್ಸಿ API ಇದಕ್ಕಾಗಿ ಜಾವಾಸ್ಕ್ರಿಪ್ಟ್‌ನ ಪ್ರಮುಖ ಸಾಧನವಾಗಿದೆ. ಇದು ನಿಮಗೆ ಇನ್ನೊಂದು ಆಬ್ಜೆಕ್ಟ್‌ಗಾಗಿ 'ಪ್ರಾಕ್ಸಿ' ರಚಿಸಲು ಅನುವು ಮಾಡಿಕೊಡುತ್ತದೆ, ಅದು ಆ ಆಬ್ಜೆಕ್ಟ್‌ನ ಮೂಲಭೂತ ಕಾರ್ಯಾಚರಣೆಗಳನ್ನು ತಡೆಹಿಡಿಯಬಹುದು ಮತ್ತು ಮರುವ್ಯಾಖ್ಯಾನಿಸಬಹುದು. ಇದು ಒಂದು ಆಬ್ಜೆಕ್ಟ್‌ನ ಮುಂದೆ ಕಸ್ಟಮೈಸ್ ಮಾಡಬಹುದಾದ ಗೇಟ್‌ಕೀಪರ್ ಅನ್ನು ಇರಿಸಿದಂತೆ, ಅದನ್ನು ಹೇಗೆ ಪ್ರವೇಶಿಸಲಾಗುತ್ತದೆ ಮತ್ತು ಮಾರ್ಪಡಿಸಲಾಗುತ್ತದೆ ಎಂಬುದರ ಮೇಲೆ ನಿಮಗೆ ಸಂಪೂರ್ಣ ನಿಯಂತ್ರಣವನ್ನು ನೀಡುತ್ತದೆ.

ಈ ಸಮಗ್ರ ಮಾರ್ಗದರ್ಶಿ ಪ್ರಾಕ್ಸಿ API ಅನ್ನು ಸರಳೀಕರಿಸುತ್ತದೆ. ನಾವು ಅದರ ಪ್ರಮುಖ ಪರಿಕಲ್ಪನೆಗಳನ್ನು ಅನ್ವೇಷಿಸುತ್ತೇವೆ, ಪ್ರಾಯೋಗಿಕ ಉದಾಹರಣೆಗಳೊಂದಿಗೆ ಅದರ ವಿವಿಧ ಸಾಮರ್ಥ್ಯಗಳನ್ನು ವಿಭಜಿಸುತ್ತೇವೆ ಮತ್ತು ಸುಧಾರಿತ ಬಳಕೆಯ ಸಂದರ್ಭಗಳು ಮತ್ತು ಕಾರ್ಯಕ್ಷಮತೆಯ ಪರಿಗಣನೆಗಳನ್ನು ಚರ್ಚಿಸುತ್ತೇವೆ. ಕೊನೆಯಲ್ಲಿ, ಆಧುನಿಕ ಫ್ರೇಮ್‌ವರ್ಕ್‌ಗಳಲ್ಲಿ ಪ್ರಾಕ್ಸಿಗಳು ಏಕೆ ಒಂದು ಮೂಲಾಧಾರವಾಗಿವೆ ಮತ್ತು ಸ್ವಚ್ಛ, ಹೆಚ್ಚು ಶಕ್ತಿಶಾಲಿ ಮತ್ತು ಹೆಚ್ಚು ನಿರ್ವಹಿಸಬಲ್ಲ ಕೋಡ್ ಬರೆಯಲು ನೀವು ಅವುಗಳನ್ನು ಹೇಗೆ ಬಳಸಿಕೊಳ್ಳಬಹುದು ಎಂಬುದನ್ನು ನೀವು ಅರ್ಥಮಾಡಿಕೊಳ್ಳುವಿರಿ.

ಮೂಲ ಪರಿಕಲ್ಪನೆಗಳನ್ನು ಅರ್ಥಮಾಡಿಕೊಳ್ಳುವುದು: ಟಾರ್ಗೆಟ್, ಹ್ಯಾಂಡ್ಲರ್, ಮತ್ತು ಟ್ರ್ಯಾಪ್‌ಗಳು

ಪ್ರಾಕ್ಸಿ API ಮೂರು ಮೂಲಭೂತ ಅಂಶಗಳ ಮೇಲೆ ನಿರ್ಮಿಸಲ್ಪಟ್ಟಿದೆ. ಅವುಗಳ ಪಾತ್ರಗಳನ್ನು ಅರ್ಥಮಾಡಿಕೊಳ್ಳುವುದು ಪ್ರಾಕ್ಸಿಗಳನ್ನು ಕರಗತ ಮಾಡಿಕೊಳ್ಳಲು ಪ್ರಮುಖವಾಗಿದೆ.

ಪ್ರಾಕ್ಸಿ ರಚಿಸುವ ಸಿಂಟ್ಯಾಕ್ಸ್ ನೇರವಾಗಿರುತ್ತದೆ:

const proxy = new Proxy(target, handler);

ಬಹಳ ಮೂಲಭೂತ ಉದಾಹರಣೆಯನ್ನು ನೋಡೋಣ. ನಾವು ಖಾಲಿ ಹ್ಯಾಂಡ್ಲರ್ ಬಳಸಿ ಎಲ್ಲಾ ಕಾರ್ಯಾಚರಣೆಗಳನ್ನು ಟಾರ್ಗೆಟ್ ಆಬ್ಜೆಕ್ಟ್‌ಗೆ ರವಾನಿಸುವ ಪ್ರಾಕ್ಸಿಯನ್ನು ರಚಿಸುತ್ತೇವೆ.


// The original object
const target = {
  message: "Hello, World!"
};

// An empty handler. All operations will be forwarded to the target.
const handler = {};

// The proxy object
const proxy = new Proxy(target, handler);

// Accessing a property on the proxy
console.log(proxy.message); // Output: Hello, World!

// The operation was forwarded to the target
console.log(target.message); // Output: Hello, World!

// Modifying a property through the proxy
proxy.anotherMessage = "Hello, Proxy!";

console.log(proxy.anotherMessage); // Output: Hello, Proxy!
console.log(target.anotherMessage); // Output: Hello, Proxy!

ಈ ಉದಾಹರಣೆಯಲ್ಲಿ, ಪ್ರಾಕ್ಸಿ ಮೂಲ ಆಬ್ಜೆಕ್ಟ್‌ನಂತೆಯೇ ನಿಖರವಾಗಿ ವರ್ತಿಸುತ್ತದೆ. ನಾವು ಹ್ಯಾಂಡ್ಲರ್‌ನಲ್ಲಿ ಟ್ರ್ಯಾಪ್‌ಗಳನ್ನು ವ್ಯಾಖ್ಯಾನಿಸಲು ಪ್ರಾರಂಭಿಸಿದಾಗ ನಿಜವಾದ ಶಕ್ತಿ ಬರುತ್ತದೆ.

ಪ್ರಾಕ್ಸಿಯ ರಚನೆ: ಸಾಮಾನ್ಯ ಟ್ರ್ಯಾಪ್‌ಗಳನ್ನು ಅನ್ವೇಷಿಸುವುದು

ಹ್ಯಾಂಡ್ಲರ್ ಆಬ್ಜೆಕ್ಟ್ 13 ವಿವಿಧ ಟ್ರ್ಯಾಪ್‌ಗಳನ್ನು ಒಳಗೊಂಡಿರಬಹುದು, ಪ್ರತಿಯೊಂದೂ ಜಾವಾಸ್ಕ್ರಿಪ್ಟ್ ಆಬ್ಜೆಕ್ಟ್‌ಗಳ ಮೂಲಭೂತ ಆಂತರಿಕ ಮೆಥಡ್‌ಗೆ ಅನುರೂಪವಾಗಿದೆ. ಅತ್ಯಂತ ಸಾಮಾನ್ಯ ಮತ್ತು ಉಪಯುಕ್ತವಾದವುಗಳನ್ನು ಅನ್ವೇಷಿಸೋಣ.

ಪ್ರಾಪರ್ಟಿ ಅಕ್ಸೆಸ್ ಟ್ರ್ಯಾಪ್‌ಗಳು

1. `get(target, property, receiver)`

ಇದು ಬಹುಶಃ ಅತಿ ಹೆಚ್ಚು ಬಳಸಲಾಗುವ ಟ್ರ್ಯಾಪ್ ಆಗಿದೆ. ಪ್ರಾಕ್ಸಿಯ ಪ್ರಾಪರ್ಟಿಯನ್ನು ಓದಿದಾಗ ಇದು ಪ್ರಚೋದಿಸಲ್ಪಡುತ್ತದೆ.

ಉದಾಹರಣೆ: ಅಸ್ತಿತ್ವದಲ್ಲಿಲ್ಲದ ಪ್ರಾಪರ್ಟಿಗಳಿಗೆ ಡೀಫಾಲ್ಟ್ ಮೌಲ್ಯಗಳು.


const user = {
  firstName: 'John',
  lastName: 'Doe',
  age: 30
};

const userHandler = {
  get(target, property) {
    // If the property exists on the target, return it.
    // Otherwise, return a default message.
    return property in target ? target[property] : `Property '${property}' does not exist.`;
  }
};

const userProxy = new Proxy(user, userHandler);

console.log(userProxy.firstName); // Output: John
console.log(userProxy.age);       // Output: 30
console.log(userProxy.country);   // Output: Property 'country' does not exist.

2. `set(target, property, value, receiver)`

ಪ್ರಾಕ್ಸಿಯ ಪ್ರಾಪರ್ಟಿಗೆ ಮೌಲ್ಯವನ್ನು ನಿಯೋಜಿಸಿದಾಗ set ಟ್ರ್ಯಾಪ್ ಅನ್ನು ಕರೆಯಲಾಗುತ್ತದೆ. ಇದು ಮೌಲ್ಯೀಕರಣ, ಲಾಗಿಂಗ್, ಅಥವಾ ರೀಡ್-ಓನ್ಲಿ ಆಬ್ಜೆಕ್ಟ್‌ಗಳನ್ನು ರಚಿಸಲು ಪರಿಪೂರ್ಣವಾಗಿದೆ.

ಉದಾಹರಣೆ: ಡೇಟಾ ಮೌಲ್ಯೀಕರಣ (Validation).


const person = {
  name: 'Jane Doe',
  age: 25
};

const validationHandler = {
  set(target, property, value) {
    if (property === 'age') {
      if (typeof value !== 'number' || !Number.isInteger(value)) {
        throw new TypeError('Age must be an integer.');
      }
      if (value <= 0) {
        throw new RangeError('Age must be a positive number.');
      }
    }

    // If validation passes, set the value on the target object.
    target[property] = value;

    // Indicate success.
    return true;
  }
};

const personProxy = new Proxy(person, validationHandler);

personProxy.age = 30; // This is valid
console.log(personProxy.age); // Output: 30

try {
  personProxy.age = 'thirty'; // Throws TypeError
} catch (e) {
  console.error(e.message); // Output: Age must be an integer.
}

try {
  personProxy.age = -5; // Throws RangeError
} catch (e) {
  console.error(e.message); // Output: Age must be a positive number.
}

3. `has(target, property)`

ಈ ಟ್ರ್ಯಾಪ್ in ಆಪರೇಟರ್ ಅನ್ನು ತಡೆಹಿಡಿಯುತ್ತದೆ. ಯಾವ ಪ್ರಾಪರ್ಟಿಗಳು ಆಬ್ಜೆಕ್ಟ್‌ನಲ್ಲಿ ಅಸ್ತಿತ್ವದಲ್ಲಿವೆ ಎಂದು ನಿಯಂತ್ರಿಸಲು ಇದು ನಿಮಗೆ ಅನುವು ಮಾಡಿಕೊಡುತ್ತದೆ.

ಉದಾಹರಣೆ: 'ಖಾಸಗಿ' (private) ಪ್ರಾಪರ್ಟಿಗಳನ್ನು ಮರೆಮಾಡುವುದು.

ಜಾವಾಸ್ಕ್ರಿಪ್ಟ್‌ನಲ್ಲಿ, ಖಾಸಗಿ ಪ್ರಾಪರ್ಟಿಗಳಿಗೆ ಅಂಡರ್‌ಸ್ಕೋರ್ (_) ನೊಂದಿಗೆ ಪೂರ್ವಪ್ರತ್ಯಯ ನೀಡುವುದು ಸಾಮಾನ್ಯ ಸಂಪ್ರದಾಯವಾಗಿದೆ. ನಾವು has ಟ್ರ್ಯಾಪ್ ಬಳಸಿ ಇವುಗಳನ್ನು in ಆಪರೇಟರ್‌ನಿಂದ ಮರೆಮಾಡಬಹುದು.


const secretData = {
  _apiKey: 'xyz123abc',
  publicKey: 'pub456def',
  id: 1
};

const hidingHandler = {
  has(target, property) {
    if (property.startsWith('_')) {
      return false; // Pretend it doesn't exist
    }
    return property in target;
  }
};

const dataProxy = new Proxy(secretData, hidingHandler);

console.log('publicKey' in dataProxy); // Output: true
console.log('_apiKey' in dataProxy);   // Output: false (even though it's on the target)
console.log('id' in dataProxy);        // Output: true

ಗಮನಿಸಿ: ಇದು ಕೇವಲ in ಆಪರೇಟರ್ ಮೇಲೆ ಪರಿಣಾಮ ಬೀರುತ್ತದೆ. ನೀವು ಅನುಗುಣವಾದ get ಟ್ರ್ಯಾಪ್ ಅನ್ನು ಸಹ ಕಾರ್ಯಗತಗೊಳಿಸದ ಹೊರತು dataProxy._apiKey ನಂತಹ ನೇರ ಪ್ರವೇಶವು ಇನ್ನೂ ಕಾರ್ಯನಿರ್ವಹಿಸುತ್ತದೆ.

4. `deleteProperty(target, property)`

delete ಆಪರೇಟರ್ ಬಳಸಿ ಪ್ರಾಪರ್ಟಿಯನ್ನು ಅಳಿಸಿದಾಗ ಈ ಟ್ರ್ಯಾಪ್ ಕಾರ್ಯಗತಗೊಳ್ಳುತ್ತದೆ. ಪ್ರಮುಖ ಪ್ರಾಪರ್ಟಿಗಳನ್ನು ಅಳಿಸುವುದನ್ನು ತಡೆಯಲು ಇದು ಉಪಯುಕ್ತವಾಗಿದೆ.

ಟ್ರ್ಯಾಪ್ ಯಶಸ್ವಿ ಅಳಿಸುವಿಕೆಗಾಗಿ true ಅಥವಾ ವಿಫಲವಾದರೆ false ಅನ್ನು ಹಿಂತಿರುಗಿಸಬೇಕು.

ಉದಾಹರಣೆ: ಪ್ರಾಪರ್ಟಿಗಳನ್ನು ಅಳಿಸುವುದನ್ನು ತಡೆಯುವುದು.


const immutableConfig = {
  databaseUrl: 'prod.db.server',
  port: 8080
};

const deletionGuardHandler = {
  deleteProperty(target, property) {
    if (property in target) {
      console.warn(`Attempted to delete protected property: '${property}'. Operation denied.`);
      return false;
    }
    return true; // Property didn't exist anyway
  }
};

const configProxy = new Proxy(immutableConfig, deletionGuardHandler);

delete configProxy.port;
// Console output: Attempted to delete protected property: 'port'. Operation denied.

console.log(configProxy.port); // Output: 8080 (It wasn't deleted)

ಆಬ್ಜೆಕ್ಟ್ ಎಣಿಕೆ ಮತ್ತು ವಿವರಣೆ ಟ್ರ್ಯಾಪ್‌ಗಳು

5. `ownKeys(target)`

Object.keys(), Object.getOwnPropertyNames(), Object.getOwnPropertySymbols(), ಮತ್ತು Reflect.ownKeys() ನಂತಹ, ಆಬ್ಜೆಕ್ಟ್‌ನ ಸ್ವಂತ ಪ್ರಾಪರ್ಟಿಗಳ ಪಟ್ಟಿಯನ್ನು ಪಡೆಯುವ ಕಾರ್ಯಾಚರಣೆಗಳಿಂದ ಈ ಟ್ರ್ಯಾಪ್ ಪ್ರಚೋದಿಸಲ್ಪಡುತ್ತದೆ.

ಉದಾಹರಣೆ: ಕೀಗಳನ್ನು ಫಿಲ್ಟರ್ ಮಾಡುವುದು.

ನಮ್ಮ ಹಿಂದಿನ 'ಖಾಸಗಿ' ಪ್ರಾಪರ್ಟಿ ಉದಾಹರಣೆಯೊಂದಿಗೆ ಇದನ್ನು ಸಂಯೋಜಿಸಿ ಅವುಗಳನ್ನು ಸಂಪೂರ್ಣವಾಗಿ ಮರೆಮಾಡೋಣ.


const secretData = {
  _apiKey: 'xyz123abc',
  publicKey: 'pub456def',
  id: 1
};

const keyHidingHandler = {
  has(target, property) {
    return !property.startsWith('_') && property in target;
  },
  ownKeys(target) {
    return Reflect.ownKeys(target).filter(key => !key.startsWith('_'));
  },
  get(target, property, receiver) {
    // Also prevent direct access
    if (property.startsWith('_')) {
      return undefined;
    }
    return Reflect.get(target, property, receiver);
  }
};

const fullProxy = new Proxy(secretData, keyHidingHandler);

console.log(Object.keys(fullProxy)); // Output: ['publicKey', 'id']
console.log('publicKey' in fullProxy); // Output: true
console.log('_apiKey' in fullProxy);   // Output: false
console.log(fullProxy._apiKey);      // Output: undefined

ಇಲ್ಲಿ ನಾವು Reflect ಬಳಸುತ್ತಿರುವುದನ್ನು ಗಮನಿಸಿ. Reflect ಆಬ್ಜೆಕ್ಟ್ ಜಾವಾಸ್ಕ್ರಿಪ್ಟ್‌ನ ತಡೆಹಿಡಿಯಬಹುದಾದ ಕಾರ್ಯಾಚರಣೆಗಳಿಗಾಗಿ ಮೆಥಡ್‌ಗಳನ್ನು ಒದಗಿಸುತ್ತದೆ, ಮತ್ತು ಅದರ ಮೆಥಡ್‌ಗಳು ಪ್ರಾಕ್ಸಿ ಟ್ರ್ಯಾಪ್‌ಗಳಂತೆಯೇ ಅದೇ ಹೆಸರು ಮತ್ತು ಸಹಿಯನ್ನು ಹೊಂದಿರುತ್ತವೆ. ಡೀಫಾಲ್ಟ್ ನಡವಳಿಕೆಯನ್ನು ಸರಿಯಾಗಿ ನಿರ್ವಹಿಸುವುದನ್ನು ಖಚಿತಪಡಿಸಿಕೊಳ್ಳಲು, ಮೂಲ ಕಾರ್ಯಾಚರಣೆಯನ್ನು ಟಾರ್ಗೆಟ್‌ಗೆ ಫಾರ್ವರ್ಡ್ ಮಾಡಲು Reflect ಬಳಸುವುದು ಉತ್ತಮ ಅಭ್ಯಾಸವಾಗಿದೆ.

ಫಂಕ್ಷನ್ ಮತ್ತು ಕನ್‌ಸ್ಟ್ರಕ್ಟರ್ ಟ್ರ್ಯಾಪ್‌ಗಳು

ಪ್ರಾಕ್ಸಿಗಳು ಕೇವಲ ಪ್ಲೇನ್ ಆಬ್ಜೆಕ್ಟ್‌ಗಳಿಗೆ ಸೀಮಿತವಾಗಿಲ್ಲ. ಟಾರ್ಗೆಟ್ ಒಂದು ಫಂಕ್ಷನ್ ಆಗಿರುವಾಗ, ನೀವು ಕಾಲ್‌ಗಳು ಮತ್ತು ಕನ್‌ಸ್ಟ್ರಕ್ಷನ್‌ಗಳನ್ನು ತಡೆಹಿಡಿಯಬಹುದು.

6. `apply(target, thisArg, argumentsList)`

ಒಂದು ಫಂಕ್ಷನ್‌ನ ಪ್ರಾಕ್ಸಿಯನ್ನು ಎಕ್ಸಿಕ್ಯೂಟ್ ಮಾಡಿದಾಗ ಈ ಟ್ರ್ಯಾಪ್ ಅನ್ನು ಕರೆಯಲಾಗುತ್ತದೆ. ಇದು ಫಂಕ್ಷನ್ ಕಾಲ್ ಅನ್ನು ತಡೆಹಿಡಿಯುತ್ತದೆ.

ಉದಾಹರಣೆ: ಫಂಕ್ಷನ್ ಕಾಲ್‌ಗಳು ಮತ್ತು ಅವುಗಳ ಆರ್ಗ್ಯುಮೆಂಟ್‌ಗಳನ್ನು ಲಾಗ್ ಮಾಡುವುದು.


function sum(a, b) {
  return a + b;
}

const loggingHandler = {
  apply(target, thisArg, argumentsList) {
    console.log(`Calling function '${target.name}' with arguments: ${argumentsList}`);
    // Execute the original function with the correct context and arguments
    const result = Reflect.apply(target, thisArg, argumentsList);
    console.log(`Function '${target.name}' returned: ${result}`);
    return result;
  }
};

const proxiedSum = new Proxy(sum, loggingHandler);

proxiedSum(5, 10);
// Console output:
// Calling function 'sum' with arguments: 5,10
// Function 'sum' returned: 15

7. `construct(target, argumentsList, newTarget)`

ಈ ಟ್ರ್ಯಾಪ್ ಒಂದು ಕ್ಲಾಸ್ ಅಥವಾ ಫಂಕ್ಷನ್‌ನ ಪ್ರಾಕ್ಸಿಯಲ್ಲಿ new ಆಪರೇಟರ್‌ನ ಬಳಕೆಯನ್ನು ತಡೆಹಿಡಿಯುತ್ತದೆ.

ಉದಾಹರಣೆ: ಸಿಂಗಲ್‌ಟನ್ ಪ್ಯಾಟರ್ನ್ ಅನುಷ್ಠಾನ.


class MyDatabaseConnection {
  constructor(url) {
    this.url = url;
    console.log(`Connecting to ${this.url}...`);
  }
}

let instance;

const singletonHandler = {
  construct(target, argumentsList) {
    if (!instance) {
      console.log('Creating new instance.');
      instance = Reflect.construct(target, argumentsList);
    }
    console.log('Returning existing instance.');
    return instance;
  }
};

const ProxiedConnection = new Proxy(MyDatabaseConnection, singletonHandler);

const conn1 = new ProxiedConnection('db://primary');
// Console output:
// Creating new instance.
// Connecting to db://primary...
// Returning existing instance.

const conn2 = new ProxiedConnection('db://secondary'); // URL will be ignored
// Console output:
// Returning existing instance.

console.log(conn1 === conn2); // Output: true
console.log(conn1.url); // Output: db://primary
console.log(conn2.url); // Output: db://primary

ಪ್ರಾಯೋಗಿಕ ಬಳಕೆಯ ಸಂದರ್ಭಗಳು ಮತ್ತು ಸುಧಾರಿತ ಪ್ಯಾಟರ್ನ್‌ಗಳು

ಈಗ ನಾವು ಪ್ರತ್ಯೇಕ ಟ್ರ್ಯಾಪ್‌ಗಳನ್ನು ಚರ್ಚಿಸಿದ್ದೇವೆ, ನೈಜ-ಪ್ರಪಂಚದ ಸಮಸ್ಯೆಗಳನ್ನು ಪರಿಹರಿಸಲು ಅವುಗಳನ್ನು ಹೇಗೆ ಸಂಯೋಜಿಸಬಹುದು ಎಂಬುದನ್ನು ನೋಡೋಣ.

1. API ಅಬ್ಸ್ಟ್ರಾಕ್ಷನ್ ಮತ್ತು ಡೇಟಾ ರೂಪಾಂತರ

APIಗಳು ಸಾಮಾನ್ಯವಾಗಿ ನಿಮ್ಮ ಅಪ್ಲಿಕೇಶನ್‌ನ ಸಂಪ್ರದಾಯಗಳಿಗೆ ಹೊಂದಿಕೆಯಾಗದ ಸ್ವರೂಪದಲ್ಲಿ ಡೇಟಾವನ್ನು ಹಿಂತಿರುಗಿಸುತ್ತವೆ (ಉದಾ., snake_case vs. camelCase). ಪ್ರಾಕ್ಸಿ ಈ ಪರಿವರ್ತನೆಯನ್ನು ಪಾರದರ್ಶಕವಾಗಿ ನಿಭಾಯಿಸಬಹುದು.


function snakeToCamel(s) {
  return s.replace(/(_\w)/g, (m) => m[1].toUpperCase());
}

// Imagine this is our raw data from an API
const apiResponse = {
  user_id: 123,
  first_name: 'Alice',
  last_name: 'Wonderland',
  account_status: 'active'
};

const camelCaseHandler = {
  get(target, property) {
    const camelCaseProperty = snakeToCamel(property);
    // Check if the camelCase version exists directly
    if (camelCaseProperty in target) {
      return target[camelCaseProperty];
    }
    // Fallback to original property name
    if (property in target) {
      return target[property];
    }
    return undefined;
  }
};

const userModel = new Proxy(apiResponse, camelCaseHandler);

// We can now access properties using camelCase, even though they are stored as snake_case
console.log(userModel.userId);        // Output: 123
console.log(userModel.firstName);     // Output: Alice
console.log(userModel.accountStatus); // Output: active

2. ಅಬ್ಸರ್ವೇಬಲ್‌ಗಳು ಮತ್ತು ಡೇಟಾ ಬೈಂಡಿಂಗ್ (ಆಧುನಿಕ ಫ್ರೇಮ್‌ವರ್ಕ್‌ಗಳ ತಿರುಳು)

Vue 3 ನಂತಹ ಆಧುನಿಕ ಫ್ರೇಮ್‌ವರ್ಕ್‌ಗಳಲ್ಲಿನ ರಿಯಾಕ್ಟಿವಿಟಿ ಸಿಸ್ಟಮ್‌ಗಳ ಹಿಂದಿನ ಎಂಜಿನ್ ಪ್ರಾಕ್ಸಿಗಳಾಗಿವೆ. ನೀವು ಪ್ರಾಕ್ಸಿಡ್ ಸ್ಟೇಟ್ ಆಬ್ಜೆಕ್ಟ್‌ನಲ್ಲಿ ಪ್ರಾಪರ್ಟಿಯನ್ನು ಬದಲಾಯಿಸಿದಾಗ, UI ಅಥವಾ ಅಪ್ಲಿಕೇಶನ್‌ನ ಇತರ ಭಾಗಗಳಲ್ಲಿ ಅಪ್‌ಡೇಟ್‌ಗಳನ್ನು ಪ್ರಚೋದಿಸಲು set ಟ್ರ್ಯಾಪ್ ಅನ್ನು ಬಳಸಬಹುದು.

ಇಲ್ಲಿ ಒಂದು ಅತ್ಯಂತ ಸರಳೀಕೃತ ಉದಾಹರಣೆ ಇದೆ:


function createObservable(target, callback) {
  const handler = {
    set(obj, prop, value) {
      const result = Reflect.set(obj, prop, value);
      callback(prop, value); // Trigger the callback on change
      return result;
    }
  };
  return new Proxy(target, handler);
}

const state = {
  count: 0,
  message: 'Hello'
};

function render(prop, value) {
  console.log(`CHANGE DETECTED: The property '${prop}' was set to '${value}'. Re-rendering UI...`);
}

const observableState = createObservable(state, render);

observableState.count = 1;
// Console output: CHANGE DETECTED: The property 'count' was set to '1'. Re-rendering UI...

observableState.message = 'Goodbye';
// Console output: CHANGE DETECTED: The property 'message' was set to 'Goodbye'. Re-rendering UI...

3. ನಕಾರಾತ್ಮಕ ಅರೇ ಇಂಡೆಕ್ಸ್‌ಗಳು

ಒಂದು ಕ್ಲಾಸಿಕ್ ಮತ್ತು ಮೋಜಿನ ಉದಾಹರಣೆಯೆಂದರೆ, ಪೈಥಾನ್‌ನಂತಹ ಭಾಷೆಗಳಂತೆಯೇ, -1 ಕೊನೆಯ ಎಲಿಮೆಂಟ್‌ ಅನ್ನು ಸೂಚಿಸುವಂತೆ, ನಕಾರಾತ್ಮಕ ಇಂಡೆಕ್ಸ್‌ಗಳನ್ನು ಬೆಂಬಲಿಸಲು ನೇಟಿವ್ ಅರೇ ನಡವಳಿಕೆಯನ್ನು ವಿಸ್ತರಿಸುವುದು.


function createNegativeArrayProxy(arr) {
  const handler = {
    get(target, property) {
      const index = Number(property);
      if (!Number.isNaN(index) && index < 0) {
        // Convert negative index to a positive one from the end
        property = String(target.length + index);
      }
      return Reflect.get(target, property);
    }
  };
  return new Proxy(arr, handler);
}

const originalArray = ['a', 'b', 'c', 'd', 'e'];
const proxiedArray = createNegativeArrayProxy(originalArray);

console.log(proxiedArray[0]);  // Output: a
console.log(proxiedArray[-1]); // Output: e
console.log(proxiedArray[-2]); // Output: d
console.log(proxiedArray.length); // Output: 5

ಕಾರ್ಯಕ್ಷಮತೆಯ ಪರಿಗಣನೆಗಳು ಮತ್ತು ಉತ್ತಮ ಅಭ್ಯಾಸಗಳು

ಪ್ರಾಕ್ಸಿಗಳು ನಂಬಲಾಗದಷ್ಟು ಶಕ್ತಿಯುತವಾಗಿದ್ದರೂ, ಅವು ಮಾಂತ್ರಿಕ ಪರಿಹಾರವಲ್ಲ. ಅವುಗಳ ಪರಿಣಾಮಗಳನ್ನು ಅರ್ಥಮಾಡಿಕೊಳ್ಳುವುದು ಬಹಳ ಮುಖ್ಯ.

ಕಾರ್ಯಕ್ಷಮತೆಯ ಓವರ್‌ಹೆಡ್

ಪ್ರಾಕ್ಸಿ ಒಂದು ಪರೋಕ್ಷ ಪದರವನ್ನು ಪರಿಚಯಿಸುತ್ತದೆ. ಪ್ರಾಕ್ಸಿಡ್ ಆಬ್ಜೆಕ್ಟ್‌ನ ಪ್ರತಿಯೊಂದು ಕಾರ್ಯಾಚರಣೆಯು ಹ್ಯಾಂಡ್ಲರ್ ಮೂಲಕ ಹಾದುಹೋಗಬೇಕು, ಇದು ಪ್ಲೇನ್ ಆಬ್ಜೆಕ್ಟ್ ಮೇಲಿನ ನೇರ ಕಾರ್ಯಾಚರಣೆಗೆ ಹೋಲಿಸಿದರೆ ಸ್ವಲ್ಪ ಪ್ರಮಾಣದ ಓವರ್‌ಹೆಡ್ ಅನ್ನು ಸೇರಿಸುತ್ತದೆ. ಹೆಚ್ಚಿನ ಅಪ್ಲಿಕೇಶನ್‌ಗಳಿಗೆ (ಡೇಟಾ ಮೌಲ್ಯೀಕರಣ ಅಥವಾ ಫ್ರೇಮ್‌ವರ್ಕ್-ಮಟ್ಟದ ರಿಯಾಕ್ಟಿವಿಟಿಯಂತಹ), ಈ ಓವರ್‌ಹೆಡ್ ನಗಣ್ಯವಾಗಿದೆ. ಆದಾಗ್ಯೂ, ಲಕ್ಷಾಂತರ ಐಟಂಗಳನ್ನು ಸಂಸ್ಕರಿಸುವ ಟೈಟ್ ಲೂಪ್‌ನಂತಹ ಕಾರ್ಯಕ್ಷಮತೆ-ನಿರ್ಣಾಯಕ ಕೋಡ್‌ನಲ್ಲಿ, ಇದು ಒಂದು ಅಡಚಣೆಯಾಗಬಹುದು. ಕಾರ್ಯಕ್ಷಮತೆ ಪ್ರಾಥಮಿಕ ಕಾಳಜಿಯಾಗಿದ್ದರೆ ಯಾವಾಗಲೂ ಬೆಂಚ್ಮಾರ್ಕ್ ಮಾಡಿ.

ಪ್ರಾಕ್ಸಿ ಇನ್ವೇರಿಯಂಟ್ಸ್ (Invariants)

ಒಂದು ಟ್ರ್ಯಾಪ್ ಟಾರ್ಗೆಟ್ ಆಬ್ಜೆಕ್ಟ್‌ನ ಸ್ವರೂಪದ ಬಗ್ಗೆ ಸಂಪೂರ್ಣವಾಗಿ ಸುಳ್ಳು ಹೇಳಲು ಸಾಧ್ಯವಿಲ್ಲ. ಜಾವಾಸ್ಕ್ರಿಪ್ಟ್ 'ಇನ್ವೇರಿಯಂಟ್ಸ್' ಎಂದು ಕರೆಯಲ್ಪಡುವ ನಿಯಮಗಳ ಗುಂಪನ್ನು ಜಾರಿಗೊಳಿಸುತ್ತದೆ, ಇದನ್ನು ಪ್ರಾಕ್ಸಿ ಟ್ರ್ಯಾಪ್‌ಗಳು ಪಾಲಿಸಬೇಕು. ಇನ್ವೇರಿಯಂಟ್ ಅನ್ನು ಉಲ್ಲಂಘಿಸುವುದರಿಂದ TypeError ಉಂಟಾಗುತ್ತದೆ.

ಉದಾಹರಣೆಗೆ, deleteProperty ಟ್ರ್ಯಾಪ್‌ಗಾಗಿ ಒಂದು ಇನ್ವೇರಿಯಂಟ್ ಎಂದರೆ, ಟಾರ್ಗೆಟ್ ಆಬ್ಜೆಕ್ಟ್‌ನ ಅನುಗುಣವಾದ ಪ್ರಾಪರ್ಟಿ ನಾನ್-ಕಾನ್ಫಿಗರಬಲ್ ಆಗಿದ್ದರೆ ಅದು true (ಯಶಸ್ಸನ್ನು ಸೂಚಿಸುತ್ತದೆ) ಹಿಂತಿರುಗಿಸಲು ಸಾಧ್ಯವಿಲ್ಲ. ಇದು ಅಳಿಸಲಾಗದ ಪ್ರಾಪರ್ಟಿಯನ್ನು ಅಳಿಸಿದೆ ಎಂದು ಪ್ರಾಕ್ಸಿ ಹೇಳಿಕೊಳ್ಳುವುದನ್ನು ತಡೆಯುತ್ತದೆ.


const target = {};
Object.defineProperty(target, 'unbreakable', { value: 10, configurable: false });

const handler = {
  deleteProperty(target, prop) {
    // This will violate the invariant
    return true;
  }
};

const proxy = new Proxy(target, handler);

try {
  delete proxy.unbreakable; // This will throw an error
} catch (e) {
  console.error(e.message);
  // Output: 'deleteProperty' on proxy: returned true for non-configurable property 'unbreakable'
}

ಪ್ರಾಕ್ಸಿಗಳನ್ನು ಯಾವಾಗ ಬಳಸಬೇಕು (ಮತ್ತು ಯಾವಾಗ ಬಳಸಬಾರದು)

ಹಿಂತೆಗೆದುಕೊಳ್ಳಬಹುದಾದ ಪ್ರಾಕ್ಸಿಗಳು (Revocable Proxies)

ನೀವು ಪ್ರಾಕ್ಸಿಯನ್ನು 'ಆಫ್' ಮಾಡಬೇಕಾದ ಸನ್ನಿವೇಶಗಳಿಗಾಗಿ (ಉದಾ., ಭದ್ರತಾ ಕಾರಣಗಳಿಗಾಗಿ ಅಥವಾ ಮೆಮೊರಿ ನಿರ್ವಹಣೆಗಾಗಿ), ಜಾವಾಸ್ಕ್ರಿಪ್ಟ್ Proxy.revocable() ಅನ್ನು ಒದಗಿಸುತ್ತದೆ. ಇದು ಪ್ರಾಕ್ಸಿ ಮತ್ತು revoke ಫಂಕ್ಷನ್ ಎರಡನ್ನೂ ಒಳಗೊಂಡಿರುವ ಆಬ್ಜೆಕ್ಟ್ ಅನ್ನು ಹಿಂತಿರುಗಿಸುತ್ತದೆ.


const target = { data: 'sensitive' };
const handler = {};

const { proxy, revoke } = Proxy.revocable(target, handler);

console.log(proxy.data); // Output: sensitive

// Now, we revoke the proxy's access
revoke();

try {
  console.log(proxy.data); // This will throw an error
} catch (e) {
  console.error(e.message);
  // Output: Cannot perform 'get' on a proxy that has been revoked
}

ಪ್ರಾಕ್ಸಿಗಳು vs. ಇತರ ಮೆಟಾಪ್ರೋಗ್ರಾಮಿಂಗ್ ತಂತ್ರಗಳು

ಪ್ರಾಕ್ಸಿಗಳಿಗಿಂತ ಮೊದಲು, ಡೆವಲಪರ್‌ಗಳು ಇದೇ ರೀತಿಯ ಗುರಿಗಳನ್ನು ಸಾಧಿಸಲು ಇತರ ವಿಧಾನಗಳನ್ನು ಬಳಸುತ್ತಿದ್ದರು. ಪ್ರಾಕ್ಸಿಗಳು ಹೇಗೆ ಹೋಲಿಕೆಯಾಗುತ್ತವೆ ಎಂಬುದನ್ನು ಅರ್ಥಮಾಡಿಕೊಳ್ಳುವುದು ಉಪಯುಕ್ತವಾಗಿದೆ.

`Object.defineProperty()`

Object.defineProperty() ನಿರ್ದಿಷ್ಟ ಪ್ರಾಪರ್ಟಿಗಳಿಗಾಗಿ ಗೆಟರ್ಸ್ ಮತ್ತು ಸೆಟ್ಟರ್‌ಗಳನ್ನು ವ್ಯಾಖ್ಯಾನಿಸುವ ಮೂಲಕ ನೇರವಾಗಿ ಆಬ್ಜೆಕ್ಟ್ ಅನ್ನು ಮಾರ್ಪಡಿಸುತ್ತದೆ. ಮತ್ತೊಂದೆಡೆ, ಪ್ರಾಕ್ಸಿಗಳು ಮೂಲ ಆಬ್ಜೆಕ್ಟ್ ಅನ್ನು ಮಾರ್ಪಡಿಸುವುದಿಲ್ಲ; ಅವು ಅದನ್ನು ಸುತ್ತುವರಿಯುತ್ತವೆ.

ತೀರ್ಮಾನ: ವರ್ಚುವಲೈಸೇಶನ್‌ನ ಶಕ್ತಿ

ಜಾವಾಸ್ಕ್ರಿಪ್ಟ್ ಪ್ರಾಕ್ಸಿ API ಕೇವಲ ಒಂದು ಚಾಣಾಕ್ಷ ವೈಶಿಷ್ಟ್ಯಕ್ಕಿಂತ ಹೆಚ್ಚಾಗಿದೆ; ಇದು ನಾವು ಆಬ್ಜೆಕ್ಟ್‌ಗಳನ್ನು ಹೇಗೆ ವಿನ್ಯಾಸಗೊಳಿಸಬಹುದು ಮತ್ತು ಅವುಗಳೊಂದಿಗೆ ಸಂವಹನ ನಡೆಸಬಹುದು ಎಂಬುದರಲ್ಲಿ ಒಂದು ಮೂಲಭೂತ ಬದಲಾವಣೆಯಾಗಿದೆ. ಮೂಲಭೂತ ಕಾರ್ಯಾಚರಣೆಗಳನ್ನು ತಡೆಹಿಡಿಯಲು ಮತ್ತು ಕಸ್ಟಮೈಸ್ ಮಾಡಲು ನಮಗೆ ಅನುವು ಮಾಡಿಕೊಡುವ ಮೂಲಕ, ಪ್ರಾಕ್ಸಿಗಳು ಶಕ್ತಿಯುತ ಪ್ಯಾಟರ್ನ್‌ಗಳ ಜಗತ್ತಿಗೆ ಬಾಗಿಲು ತೆರೆಯುತ್ತವೆ: ತಡೆರಹಿತ ಡೇಟಾ ಮೌಲ್ಯೀಕರಣ ಮತ್ತು ರೂಪಾಂತರದಿಂದ ಹಿಡಿದು ಆಧುನಿಕ ಬಳಕೆದಾರ ಇಂಟರ್ಫೇಸ್‌ಗಳನ್ನು ಚಾಲನೆ ಮಾಡುವ ರಿಯಾಕ್ಟಿವ್ ಸಿಸ್ಟಮ್‌ಗಳವರೆಗೆ.

ಅವುಗಳು ಸಣ್ಣ ಕಾರ್ಯಕ್ಷಮತೆಯ ವೆಚ್ಚ ಮತ್ತು ಅನುಸರಿಸಬೇಕಾದ ನಿಯಮಗಳ ಗುಂಪಿನೊಂದಿಗೆ ಬಂದರೂ, ಸ್ವಚ್ಛ, ಬೇರ್ಪಟ್ಟ ಮತ್ತು ಶಕ್ತಿಯುತ ಅಮೂರ್ತತೆಗಳನ್ನು ರಚಿಸುವ ಅವುಗಳ ಸಾಮರ್ಥ್ಯವು ಸಾಟಿಯಿಲ್ಲದ್ದು. ಆಬ್ಜೆಕ್ಟ್‌ಗಳನ್ನು ವರ್ಚುವಲೈಸ್ ಮಾಡುವ ಮೂಲಕ, ನೀವು ಹೆಚ್ಚು ದೃಢವಾದ, ನಿರ್ವಹಿಸಬಲ್ಲ ಮತ್ತು ಅಭಿವ್ಯಕ್ತಿಶೀಲ ವ್ಯವಸ್ಥೆಗಳನ್ನು ನಿರ್ಮಿಸಬಹುದು. ಮುಂದಿನ ಬಾರಿ ನೀವು ಡೇಟಾ ನಿರ್ವಹಣೆ, ಮೌಲ್ಯೀಕರಣ, ಅಥವಾ ವೀಕ್ಷಣೆಗೆ ಸಂಬಂಧಿಸಿದ ಸಂಕೀರ್ಣ ಸವಾಲನ್ನು ಎದುರಿಸಿದಾಗ, ಪ್ರಾಕ್ಸಿ ಸರಿಯಾದ ಸಾಧನವೇ ಎಂದು ಪರಿಗಣಿಸಿ. ಇದು ನಿಮ್ಮ ಟೂಲ್‌ಕಿಟ್‌ನಲ್ಲಿ ಅತ್ಯಂತ ಸೊಗಸಾದ ಪರಿಹಾರವಾಗಿರಬಹುದು.

ಜಾವಾಸ್ಕ್ರಿಪ್ಟ್ ಪ್ರಾಕ್ಸಿ API: ಆಬ್ಜೆಕ್ಟ್ ವರ್ತನೆಯ ಮಾರ್ಪಾಡಿನ ಒಂದು ಆಳವಾದ ನೋಟ | MLOG