Proxy Pattern in Javascript
As is apparent from the name, the Proxy pattern provides a layer over an object that modifies access to that object in some way. In the object-oriented programming paradigm, this is used to enforce consistency between an object’s advertised interface and its behaviour. In JavaScript, both properties and methods are From the name itself, the Proxy pattern provides a surrogate for an object that gives access to other object. In this case, object-oriented programming work as what they are advertise with the use of their interface. These can be properties and methods.
Clients usually require objects to work quickly and efficiently in an orderly manner. But there are situations that an object are severely used and may not live to its purpose. In situations like these you need to apply the Proxy pattern to create a proxy object that will act as the original object. The Proxy forwards the request to a target object and the client may not be fully aware that they are not dealing with the “original” object.
The Proxy pattern contains the following objects. The client in which it will be the one who will call the Proxy operation. The second one is the Proxy. That will provides the interface to the real object and it will maintain the reference of the real object.
Here’s a basic example.
var listener = {
get: function(target, name){
return name in target?
target[name] :
99; // default value
}
};
var p = new Proxy({}, listener);
p.a = 23;
p.b = "I am a String";
console.log(p.a);// 1
console.log(p.b);// I am a string
console.log('c' in p, p.c); // false, 99
In this example, the number 99 will be returned as the default value whenever a property name is not inside the object. It will get by using the get handler.
function CarMaker() {
this.getCar = function(car) {
if (car === "Honda") {
return "Honda City";
} else if (car === "Toyota") {
return "Toyota Altis";
} else if (car === "Mitsubishi") {
return "Mitsubishi Lancer";
} else if (car === "Ferrari") {
return "Ferrari Enzio";
} else {
return "";
}
};
}
function CarMakerProxy() {
var carmaker = new CarMaker();
var carcache = {};
return {
getCar: function(address) {
if (!carcache[car]) {
carcache[car] = carmaker.getCar(car);
}
log.add(car + ": " + carcache[car]);
return carcache[car];
},
getCount: function() {
var count = 0;
for (var code in carcache) { count++; }
return count;
}
};
};
// log helper
var log = (function() {
var log = "";
return {
add: function(msg) { log += msg + "\n"; },
show: function() { alert(log); log = ""; }
}
})();
function run() {
var chauffer = new CarMaker();s
chauffer.getCar("Honda");
chauffer.getCar("Toyota");
chauffer.getCar("Mitsubishi");
chauffer.getCar("Ferrari");
chauffer.getCar("Toyota");
chauffer.getCar("Ferrari");
chauffer.getCar("Ferrari");
log.add("\nCache size: " + chauffer.getCount());
log.show();
}
run();
In the example above the CarMaker object simulates the actual creation of cars from different car manufacturers. In which you will provide what type of car you would want depending on the car manufacturer being passed. Our CarMaker can accommodate 4 different types of car manufacturers which is equivalent to the many hundreds of automobile makers all over the world.
In this example we have decided to implement a Proxy pattern because CarMaker is quite slow in handling request. The proxy object named as CarMakerProxy will handly the many repeated request for the same automobile manufacturer being selected. To make things faster, the CarMaker Proxy has a cache that keeps frequently selected automobile manufacturers. If the automobile manufacturer is not yet included, it will got to the CarMaker service and will be stored there as a cache.
Here’s another example.
var products = new Proxy([
{ name: 'Spam', type: 'canned' },
{ name: 'Carrots', type: 'vegetable' },
{ name: 'Rice', type: 'canned' },
{ name: 'Pork Chop', type: 'meat' }
],
{
get: function(obj, prop) {
if (prop in obj) {
return obj[prop];
}
if (prop === 'number') {
return obj.length;
}
var result, types = {};
for (var product of obj) {
if (product.name === prop) {
result = product;
}
if (types[product.type]) {
types[product.type].push(product);
} else {
types[product.type] = [product];
}
}
// Get the product name
if (result) {
return result;
}
// Get product
if (prop in types) {
return types[prop];
}
// Get product types in array
if (prop === 'types') {
return Object.keys(types);
}
// default
return undefined;
}
});
console.log(products[0]); // returns Object {name: "Spam", type: "canned"}
console.log(products['Spam']); // Object {name: "Spam", type: "canned"}
console.log(products['Chorizo']); // undefined not in object
console.log(products.canned); // {name: "Spam", type: "canned"} {name: "'Carrots'", type: "'vegetable' "}
console.log(products.types); // ["canned", "vegetable", "meat"]
console.log(products.number);// 4
In this example, the proxy pattern extends an array with some utility features. In which you can see it can flexibly adapt to properties without using “defineProperties”. This example can be used whenever you will be searching a table row using it cell.
Some developers have shared thoughts when it comes to proxies. Most of the time they are not being used by many developers except that they may be used as a façade when it comes to dealing with the growing popularity of web services.
Recent Stories
Top DiscoverSDK Experts
Compare Products
Select up to three two products to compare by clicking on the compare icon () of each product.
{{compareToolModel.Error}}
{{CommentsModel.TotalCount}} Comments
Your Comment