Last active
December 14, 2015 08:59
-
-
Save particle4dev/5062107 to your computer and use it in GitHub Desktop.
How to implement protected properties in javascript [ES5]
This file contains 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
/** | |
* How to implement protected properties in javascript [ES5] | |
* | |
* @author Steve Hoang <particles4dev> | |
* @version | |
* @since 0.1 | |
* @inspiration WebReflection <link> | |
* | |
**/ | |
(function(){ | |
var ProtectedPropertype, Check, Extends, AccessDeniedError; | |
AccessDeniedError = function(){ | |
var name = "Access Denied Error"; | |
var message = ": protected !!!"; | |
this.getMessage = function(){ | |
return name + " " + message; | |
} | |
} | |
/** | |
* ProtectedPropertype Class | |
* | |
* Description | |
**/ | |
ProtectedPropertype = function(v){ | |
/** | |
* Private property | |
**/ | |
var that = this; | |
var value = v; | |
/** | |
* Public property | |
**/ | |
this.obj = null; | |
this.setObject = function(o){ | |
this.obj = o; | |
}; | |
this.enumerable = true; | |
this.configurable = true; | |
// Define the getter | |
this.get = function get(){ | |
var c = Check(that.obj, get.caller); | |
if(c == Extends.ISPROTECTED) return new ProtectedPropertype(value); | |
return value; | |
}; | |
// Define the setter | |
this.set = function set($value) { | |
Check(that.obj, set.caller); | |
value = $value; | |
}; | |
}; | |
this.Check = function(object, caller){ | |
/** | |
* Private property | |
**/ | |
if (caller === Check) { | |
return; | |
} | |
if (caller === Extends) { | |
return Extends.ISPROTECTED; | |
} | |
if (caller) { | |
for (var key in object) { | |
if (object[key] === caller){ | |
return; | |
} | |
} | |
} | |
throw new AccessDeniedError(); | |
}; | |
Extends = function(result){ | |
var source, obj = {}, prop, ft, fs = function(){}, s; | |
for(var i = 1, len = arguments.length; i < len; i++){ | |
source = arguments[i]; | |
if (source && typeof source == "object") { | |
for (prop in source) { | |
obj[prop] = source[prop]; | |
} | |
} | |
else if (source && typeof source == "function") { | |
//stupid ; will fix it | |
ft = new fs(); | |
s = new source(); | |
for (prop in s) { | |
ft[prop] = s[prop]; | |
} | |
source.prototype = ft; | |
fs = source; | |
} | |
} | |
var tg = new fs(); | |
for(prop in obj){ | |
tg[prop] = obj[prop]; | |
} | |
result.prototype = tg; | |
return result; | |
}; | |
Extends.ISPROTECTED = 0; | |
Object.defineProtectedProperty = (function(defineProperty){ | |
/** | |
* Class | |
* | |
* ads | |
**/ | |
return function defineProtectedProperty(object, key, description){ | |
description.setObject(object); | |
defineProperty(object, key, description); | |
}; | |
}(Object.defineProperty)); | |
console.group("Step 1 : Create object"); | |
var monkey = { | |
action: function () { | |
this._eatBanana(); | |
} | |
}; | |
console.log("var monkey = "); | |
console.log(monkey); | |
console.groupEnd(); | |
console.group("Step 2 : Add 'protected' method _eatBanana"); | |
Object.defineProtectedProperty( | |
monkey, "_eatBanana", | |
new ProtectedPropertype(function () { | |
console.log(this._eating); | |
}) | |
); | |
console.log("var monkey = "); | |
console.log(monkey); | |
console.groupEnd(); | |
console.group("Step 3 : Add 'protected' property _eating"); | |
Object.defineProtectedProperty( | |
monkey, "_eating", | |
new ProtectedPropertype("yum yum yum") | |
); | |
console.log("var monkey = "); | |
console.log(monkey); | |
console.groupEnd(); | |
console.group("Step 4 : Method call monkey._eatBanana();"); | |
try { | |
monkey._eatBanana(); | |
} catch(e) { | |
console.log(e.getMessage()); | |
} | |
console.groupEnd(); | |
console.group("Step 5 : Property access monkey._eating"); | |
try { | |
monkey._eating = "change text"; | |
} catch(e) { | |
console.log(e.getMessage()); | |
} | |
console.groupEnd(); | |
console.group("Step 6 : monkey.action();"); | |
monkey.action(); | |
console.groupEnd(); | |
console.group("Step 7 : Extends"); | |
var human = function(){ | |
this.saySomething = function(){ | |
console.log("i am human not a monkey"); | |
} | |
}; | |
var man = Extends(function(){ | |
var that = this; | |
for (prop in that) { | |
if(that[prop] instanceof ProtectedPropertype) | |
Object.defineProtectedProperty(that, prop, that[prop]); | |
} | |
}, monkey, human); | |
console.log("var man = "); | |
console.log(man); | |
console.groupEnd(); | |
console.group("Step 8 : New man"); | |
var john = new man(); | |
console.log("var john = "); | |
console.log(john); | |
console.groupEnd(); | |
try { | |
john._eatBanana(); | |
} catch(e) { | |
console.log(e.getMessage()); | |
} | |
john.saySomething(); | |
console.log(john instanceof human); | |
console.log(john instanceof man); | |
//console.log(john instanceof monkey); | |
})(); | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment