Skip to content

Instantly share code, notes, and snippets.

@kdimatteo
Forked from hagino3000/method_missing.js
Created April 6, 2014 00:27
Show Gist options
  • Save kdimatteo/9999808 to your computer and use it in GitHub Desktop.
Save kdimatteo/9999808 to your computer and use it in GitHub Desktop.
/**
* Enable route to __noSuchMethod__ when unknown method calling.
*
* @param {Object} obj Target object.
* @return {Object}
*/
function enableMethodMissing(obj) {
var functionHandler = createBaseHandler({});
functionHandler.get = function(receiver, name) {
return function(){};
}
var calledProperty;
var trapFn = Proxy.createFunction(functionHandler, function() {
return obj.__noSuchMethod__(calledProperty, Array.prototype.slice.call(arguments));
});
var propertyAccessHandler = createBaseHandler(obj);
propertyAccessHandler.get = function(receiver, name) {
if (name in obj) {
return obj[name];
} else {
calledProperty = name;
return trapFn;
}
}
return Proxy.create(propertyAccessHandler);
/**
* Create trap functions (internal)
*
* @param {Object} obj Original object.
* @return {Object} Proxy handler.
*/
function createBaseHandler(obj) {
return {
getOwnPropertyDescriptor: function(name) {
var desc = Object.getOwnPropertyDescriptor(obj, name);
if (desc !== undefined) { desc.configurable = true; }
return desc;
},
getPropertyDescriptor: function(name) {
var desc = Object.getPropertyDescriptor(obj, name);
if (desc !== undefined) { desc.configurable = true; }
return desc;
},
getOwnPropertyNames: function() {
return Object.getOwnPropertyNames(obj);
},
getPropertyNames: function() {
return Object.getPropertyNames(obj);
},
defineProperty: function(name, desc) {
return Object.defineProperty(obj, name, desc);
},
delete: function(name) {
return delete obj[name];
},
fix: function() {
if (Object.isFrozen(obj)) {
return Object.getOwnPropertyNames(obj).map(function(name) {
return Object.getOwnPropertyDescriptor(obj, name);
});
}
return undefined;
},
has: function(name) {
return name in obj;
},
hasOwn: function(name) {
return Object.prototype.hasOwnProperty.call(obj, name);
},
set: function(receiver, name, val) {
// No check
// But normally needs checking property descriptor
obj[name] = val;
},
enumerate: function() {
var result = [];
for (var name in obj) { result.push(name); }
return result;
},
keys: function() {
return Object.keys(obj);
}
};
}
}
var Ninja = function(name, age) {
this.name = name;
this.age = age;
return enableMethodMissing(this);
}
Ninja.prototype.getName = function() {
return this.name;
}
Ninja.prototype.__noSuchMethod__ = function(methodName, args) {
console.log('method name:' + methodName);
console.log(args);
};
var sasuke = new Ninja('Sasuke', 0);
sasuke.getName(); // => Sasuke
sasuke.hoge(1,2,3); // => __noSuchMethod__('hoge', [1,2,3])
sasuke.hoge; // => undefined
sasuke.age; //=> 0
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment