How to define a non-extensible javascript object - javascript

I'd like to, if possible, define a javascript object that has a few properties along with getters/setters for those properties, but I don't want others to be able to add new properties to objects without extending the object definition (similar to how one would define a class in Java/C#). Is this possible to do with javascript?

You can use the "preventExtensions" method.
var obj = { foo: 'a' };
Object.preventExtensions(obj);
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/preventExtensions

In the following way, you can freeze the instances of the objects, but leave open to inheriting classes to add their own properties:
function Animal(name, action) {
this.name = name;
this.action = action;
if (this.constructor === Animal) {
Object.freeze(this);
}
}
var dog = new Animal('rover', 'bark')
dog.run = function(){console.log('I\'m running!')} // throws type error
function Dog(name, action, bark) {
Animal.call(this, name, action)
this.bark = bark // Animal not frozen since constructor is different
Object.freeze(this)
}
var puppy = new Dog('sparky', 'run', 'woof')
puppy.isTrained = false; // throws type error
See here: http://www.2ality.com/2013/06/freezing-instances.html

You can use Object.seal(obj):
const obj = Object.seal({
a: 1,
b: "hello"
})
obj.c = "world" // silently fails

Related

How to convert an instance of a class to a string and then back to that class instance? [duplicate]

I'm writing a simple serialization / deserialization framework for some application-specific objects.
Consider the following:
"use strict";
function Dog(name) { this._name = name; };
Dog.prototype.constructor = Dog;
Dog.prototype.getName = function() { return this._name; }
var d1 = new Dog('fido');
var d2 = JSON.parse(JSON.stringify(d1)); // serialize / deserialize
> d1
Dog { _name: 'fido' }
> d1.getName()
'fido'
> d2
{ _name: 'fido' }
> d2.getName()
TypeError: d2.getName is not a function
At this point, one can ask "What does d1 have that d2 lacks?"
One approach that partially works is to manually assign the methods of d1 to d2:
> d2.constructor = d1.constructor
> d2.getName = d1.getName
> d2.getName()
'fido'
This has a couple of disadvantages. First, I have to manually assign each method of d1 to d2. Second, d2 gets its own properties, and doesn't share slots using the prototype mechanism:
> d2
Dog {
_name: 'fido',
constructor: [Function: Dog],
getName: [Function] }
So my refined question is: given an object (e.g. d2), is there a way to associate it with the prototype of another object (e.g. d1) so it inherits the same behavior?
Object.create() and Object.getOwnPropertyDescriptors() is what you need.
const obj = JSON.parse(JSON.stringify(d1))
const d3 = Object.create(Dog.prototype, Object.getOwnPropertyDescriptors(obj))
The difference between this and OP's method is that this method sets prototype properties on the prototype, whereas OP's method sets properties directly on the object. You can see this when you loop through object own properties using for-in loop with hasOwnProperty() method:
for (const i in d1) {
if (d3.hasOwnProperty(i)) {
console.log(i)
}
}
With my method it outputs only _name, but with OP's method it outputs also getName.
Unfortunately, Object.getOwnPropertyDescriptors() is part of ECMAScript 2017 and it's supported only in Firefox for now, so you'll need to use Babel.
Alternatively, you can use Object.setPrototypeOf(). It has better browser support than Object.getOwnPropertyDescriptors(), but it's discouraged by MDN, because it's slow.
const d3 = JSON.parse(JSON.stringify(d1))
Object.setPrototypeOf(d3, Dog.prototype)
As I was writing this, I had the idea of creating a custom constructor that uses the deserialized JSON to initialize the object:
Dog.createFromJSON = function(obj) {
var d = new Dog();
Object.keys(obj).forEach(function(key) {
d[key] = obj[key];
});
return d;
}
> d3 = Dog.createFromJSON(JSON.parse(JSON.serialize(d1)))
> d3
Dog { _name: 'fido' }
> d3.getName()
'fido'
Update: how to dynamically find the class and assign the prototype
As #Louis points out, #Gothdo's answer requires that you know what class the deserialized object belongs to. If you're willing to add the class name to the serialized object, you can use that to determine the class dynamically. So, for example, to expand on the OP's example:
> var d1 = new Dog('fido');
> d1['_class'] = 'Dog';
> let jsonString = JSON.stringify(d1)
'{"_name":"fido","_class":"Dog"}'
Using the trick described in deserialize JSON to JAVASCRIPT object (but tweaked for Node.js) you can use a string to get a handle to a class prototype via Node.js's global object:
> global[d1['_class']].prototype
Dog { getName: [Function] }
Now you can use that to dynamically reconstruct the object using #Gothdo's technique. Putting it all together:
/**
* Dynamically create an object from a JSON string of properties.
* Assumes the presence of a _class meta-property that names the
* resulting class.
*/
function reconstitute(jsonString) {
let obj = JSON.parse(jsonString);
let cls = global[obj['_class']];
delete obj['_class']; // remove meta-property
return Object.setPrototypeOf(obj, cls.prototype);
}
> reconstitute('{"_name":"fido","_class":"Dog"}')
Dog { _name: 'fido' }
The Best method so far would be:
let obj = Object.assign(new ClassyObject(), JSON.parse(JSON.serialize(the_obj_that_will_lost_prototype)))
Just improved and more direct:
let obj = Object.assign(new the_obj_that_will_lost_prototype.constructor(), JSON.parse(JSON.serialize(the_obj_that_will_lost_prototype)))
Simple Method: Change Class In-Place
If you really need to change the class of an object in-place, this function will work on any system that has Object.getPrototypeOf and Object.setPrototypeOf defined:
// set class of object to `name`
function setObjectClassName(obj, name) {
let newObj = eval('new ' + name + '()');
let proto = Object.getPrototypeOf(newObj);
Object.setPrototypeOf(obj, proto);
return obj;
}
Example using JSON.serialize() and JSON.parse():
class MyClass extends Object {}
let original = new MyClass();
original.foo = "bar";
console.log(original.constructor.name, original);
// MyClass { "foo": 'bar' }
let originalClassName = original.constructor.name;
let serialized = JSON.stringify(original);
console.log(serialized.constructor.name, serialized);
// String '{"foo":"bar"}'
let restored = JSON.parse(serialized);
console.log(restored.constructor.name, restored);
// Object { foo: 'bar' }
restored = setObjectClassName(restored, originalClassName);
console.log(restored.constructor.name, restored);
// MyClass { foo: 'bar' }
Better Method: Copy the Object
Mozilla warns against changing the prototype of an existing object, as it is:
a very slow operation in every browser and JavaScript engine
- Mozilla
If you don't absolutely need to change in-place, this function will copy an object and change the class of the copy:
function copyObjectAndChangeClass(obj, name) {
let newObj = eval('new ' + name + '()');
Object.assign(newObj, obj);
return newObj;
}

How do you create a javascript class with immutable properties

This question is specifically about preventing unwanted properties from being added to a javascript "class". I have a class called Animal.
function Animal(){
this.name="";
this.type="";
//20 other properties
}
What would be the easiest way for a user to create their own Animal and add 20 properties. I want to also prevent the user from accidentally adding incorrect properties.
my current method:
var myAnimal= new Animal();
myAnimal.name="fluffy";
myAnimal.type="cat";
myAnimal.typo="cat";
//adding 20 more properties would require typing myAnimal 20 more times
Plus if a user makes a typo it would add it as a new property.
I was hoping there would be something like this:
myAnimal=new Animal{
name:"fluffy",
type:"cat";
typo:"cat" //would throw an error
}
I've looked into Object.freeze Object.seal, Object.preventExtensions but not sure how they apply to classes.
You can Object.seal(this) at the end of the constructor to prevent new properties from being added:
function Animal() {
this.name = "";
this.type = "";
// 20 other properties
Object.seal(this);
}
and you can take an object with initial values in the constructor:
function Animal(initial) {
this.name = "";
this.type = "";
// 20 other properties
Object.seal(this);
Object.assign(this, initial);
}
used like so:
myAnimal = new Animal({
name: "fluffy",
type: "cat",
typo: "cat",
});
with the downside that the error doesn’t point directly at typo like it would if you used multiple assignment statements.
You can use Proxy For this.
You can set custom setter, what throw an Error when obj does not has the property.
You can do the same with get too in that case no more undefined cause of typo.
function Animal() {
this.name = "";
this.type = "";
return new Proxy(this, {
set: function(obj, prop, value) {
if (!obj.hasOwnProperty(prop))
{
throw Error("I don`t have this property: " + prop);
}
obj[prop] = value;
}
});
}
var cat = new Animal();
console.log(cat);
cat.name = "Rita";
console.log(cat);
cat.nama = "Rata";
console.log(cat);

reusable javascript objects, prototypes and scope

MyGlobalObject;
function TheFunctionICanUseRightAwaySingleForAllInstansesAndWithoutInstanse() {
function() {
alert('NO CONSTRUCTOR WAS CALLED');
}
};
The Long-named function must be callable from MyGlobalObject, which in turn must be available as a global (to window) variable in all times after script was loaded. It should support extensibility in accordance with latest standards.
I'm at architectural dilemma of how to built JS base for an application (almost 100% JS).
We need an object i.e. window.MyObject (like a module, like jQuery) so
It can be created with
VAR1
var MyGlobalObjConstructor = function(){
this.GlobalFunctionInObject = function(){
alert('called with MyGlobalObj.GlobalFunctionInObject()');
}
};
window.MyGlobalObj = new MyGlobalObjConstructor();
Is MyGlobalObj extensible? Can I create child objects, which will inherit current state of MyGlobalObj (extended functions/properties MyGlobalObj.NewFunc e.g.)? What is the main difference between using prototype (VAR3)?
By GlobaldFunction I mean single instance for all initialized/instantiated (possibly instantializable) instances..
Or with
VAR2
var MyGlobalObj = {
GlobalFunctionInObject: function...
GlobalFunctionInObject2: function...
};
MyGlobalObj.GlobalFunctionInObject();
// here I lose all hierarchy elements, no prototype,
// can I use GlobalFunctionInObject2 in GlobalFunctionInObject?
Or with
VAR3
var MyGlobalConstuctor = function(){} // already 'well-formed' object
MyGlobalConstuctor.prototype.GlobalFunctionInObject = function...
};
var MyGlobalObj = new MyGlobalConstuctor();
// so I'm sceptical to NEW, because I have ALREADY wrote my functions
// which I expect to be in memory, single instance of each of them,
// so creating MyObject2,3,4 with NEW MyGC() makes no sense to me.
// DO I REALLY HAVE TO USE "MyGlobalConstuctor.prototype." FOR EACH FUNCTION?!!!!
What's the difference defining MyGlobalObj as a function and as an object (result of func or VAR2)?
OR VAR4?
I see in Chrome Debugger both prototype and __proto__ special fields. I've read that that's OK, but why are they not saved in a single prototype?
So, what is the correct/optimal way to implement window.MyObject, so one could MyObject.MyFunction(); What are the differences (pro/contra) of variants 1 2 and 3?
Variation 1 - Mixin
function SomeType() {
var priv = "I'm private";
this.publ = "I'm public";
this.action = function() {
return priv + this.publ;
};
}
var obj = new SomeType();
With this method you are creating a new object every time you call new SomeType(), creating all its methods and adding all this method to the new object. Every time you create an object.
Pros
It looks like classical inheritance so it's easy to understand to Java-C#-C++-etc people.
It can have private variables per instance since you have one function closure per each object you create
It allows multiple inheritance, also known as Twitter-mixins or functional mixins
obj instanceof SomeType will return true
Cons
It consumes more memory as more objects you create because with each object you are creating a new closure and creating each of it's methods again.
Private properties are private, not protected, subtypes can't access them
No easy way to know if a object has some Type as superclass.
Inheritance
function SubType() {
SomeType.call(this);
this.newMethod = function() {
// can't access priv
return this.publ;
};
}
var child = new SubType();
child instanceof SomeType will return false there is no other way to know if child has SomeType methods than look if it has them one by one.
Variation 2 - Object literal with prototyping
var obj = {
publ: "I'm public",
_convention: "I'm public too, but please don't touch me!",
someMethod: function() {
return this.publ + this._convention;
}
};
In this case you are creating a single object. If you are going to need only one instance of this type it can be the best solution.
Pros
It's quick and easy to understand.
Performant
Cons
No privacy, every property is public.
Inheritance
You can inherit a object prototyping it.
var child = Object.create(obj);
child.otherMethod = function() {
return this._convention + this.publ;
};
If you are on a old browser you will need to garantee Object.create works:
if (!Object.create) {
Object.create = function(obj) {
function tmp() { }
tmp.prototype = obj;
return new tmp;
};
}
To know if a object is a prototype of another you can use
obj.isPrototypeOf(child); // true
Variation 3 - Constructor pattern
UPDATE: This is the pattern ES6 classes are sugar syntax of. If you use ES6 classes you are following this pattern under the hood.
class SomeType {
constructor() {
// REALLY important to declare every non-function property here
this.publ = "I'm public";
this._convention = "I'm public too, but please don't touch me!";
}
someMethod() {
return this.publ + this._convention;
}
}
class SubType extends SomeType {
constructor() {
super(/* parent constructor parameters here */);
this.otherValue = 'Hi';
}
otherMethod() {
return this._convention + this.publ + this.otherValue;
}
}
function SomeType() {
// REALLY important to declare every non-function property here
this.publ = "I'm public";
this._convention = "I'm public too, but please don't touch me!";
}
SomeType.prototype.someMethod = function() {
return this.publ + this._convention;
};
var obj = new SomeType();
You can re-assign the prototype insteadd of adding each method if you are not inheriting and remember to re-assign the constructor property:
SomeType.prototype = {
constructor: SomeType,
someMethod = function() {
return this.publ + this._convention;
}
};
Or use _.extend or $.extend if you have underscore or jquery in your page
_.extend(SomeType.prototype, {
someMethod = function() {
return this.publ + this._convention;
}
};
The new keyword under the hood simply does this:
function doNew(Constructor) {
var instance = Object.create(Constructor.prototype);
instance.constructor();
return instance;
}
var obj = doNew(SomeType);
What you have is a function than has no methods; it just has a prototype property with a list of functions, the new operator means to create a new object and use this function's prototype (Object.create) and constructor property as initializer.
Pros
Performant
Prototype chain will allow you to know if a object inherits from some type
Cons
Two-step inheritance
Inheritance
function SubType() {
// Step 1, exactly as Variation 1
// This inherits the non-function properties
SomeType.call(this);
this.otherValue = 'Hi';
}
// Step 2, this inherits the methods
SubType.prototype = Object.create(SomeType.prototype);
SubType.prototype.otherMethod = function() {
return this._convention + this.publ + this.otherValue;
};
var child = new SubType();
You may think it looks like a super-set of Variation 2... and you'll be right. It's like variation 2 but with a initializer function (the constructor);
child instanceof SubType and child instanceof SomeType will return both true
Curiosity: Under the hood instanceof operator does is
function isInstanceOf(obj, Type) {
return Type.prototype.isPrototypeOf(obj);
}
Variation 4 - Overwrite __proto__
When you do Object.create(obj) under the hood it does
function fakeCreate(obj) {
var child = {};
child.__proto__ = obj;
return child;
}
var child = fakeCreate(obj);
The __proto__ property modifies directly the object's hidden [Prototype] property. As this can break JavaScript behaviour, it's not standard. And the standard way is preferred (Object.create).
Pros
Quick and performant
Cons
Non-standard
Dangerous; you can't have a hashmap since the __proto__ key can change the object's prototype
Inheritance
var child = { __proto__: obj };
obj.isPrototypeOf(child); // true
Comment questions
1. var1: what happens in SomeType.call(this)? Is 'call' special function?
Oh, yes, functions are objects so they have methods, I will mention three: .call(), .apply() and .bind()
When you use .call() on a function, you can pass one extra argument, the context, the value of this inside the function, for example:
var obj = {
test: function(arg1, arg2) {
console.log(this);
console.log(arg1);
console.log(arg2);
}
};
// These two ways to invoke the function are equivalent
obj.test('hi', 'lol');
// If we call fn('hi', 'lol') it will receive "window" as "this" so we have to use call.
var fn = obj.test;
fn.call(obj, 'hi', 'lol');
So when we do SomeType.call(this) we are passing the object this to function SomeCall, as you remember this function will add methods to object this.
2. var3: With your "REALLY define properties" do you mean if I use them in functions? Is it a convention? Because getting this.newProperty without it being defined at the same level with other member functions is not a problem.
I mean any property your object will have that is not a function must be defined on the constructor, not on the prototype, otherwise you will face one of the more confusing JS problems. You can see it here, but it's outside of the focus of this question.
3. Var3: what happens if I don't re-assign constructor?
Actually you might not see the difference and this is what makes it a dangerous bug. Every function's prototype object has a constructor property so you can access the constructor from an instance.
function A() { }
// When you create a function automatically, JS does this:
// A.prototype = { constructor: A };
A.prototype.someMethod = function() {
console.log(this.constructor === A); // true
this.constructor.staticMethod();
return new this.constructor();
};
A.staticMethod = function() { };
It's not a best practice because not everybody knows about it, but sometimes it helps. But if you reassign the prototype...
A.prototype = {
someMethod = function() {
console.log(this.constructor === A); // false
console.log(this.constructor === Object); // true
this.constructor.staticMethod();
return new this.constructor();
}
};
A.prototype is a new object, a instance of Object than prototypes Object.prototype and Object.prototype.constructor is Object. Confusing, right? :P
So if you overwrite the prototype and don't reset the "constructor" property, it will refer to Object instead of A, and if you try to use the "constructor" property to access some static method you may get crazy.
I usually settle with returning an object with functions as properties:
var newCat = function (name) {
return {name: name, purr: function () {alert(name + ' purrs')}};
};
var myCat = newCat('Felix');
myCat.name; // 'Felix'
myCat.purr(); // alert fires
You can have inheritance by calling the newCat function and extend the object you get:
var newLion = function (name) {
var lion = newCat(name);
lion.roar = function () {
alert(name + ' roar loudly');
}
return lion;
}
If you want a global cats object:
var cats = (function () {
var newCat = function (name) {
return {
name: name,
purr: function () {
alert(name + ' is purring')
}
};
};
return {
newCat: newCat
};
}());
Now you can call:
var mySecondCat = cats.newCat('Alice');

is it possible to assign a prototype on an existing object in javascript?

if i have:
function Base (){
this.sayHi = function(){
alert('hi');
}
}
function Thing (val){
this.value = val;
}
var bob = new Thing("bob");
Is there some way I can now say that bob inherits from Base so that I could call:
bob.sayHi();
Basically have all the methods and properties of the Base class available on that instance?
A more relevant example with solution based on CMS's post:
Here Items could represent data returned by the server..
var Items = [
{ sku: 123, type:'buggy', title:'This is a title', description: 'this is a description' },
{ sku: 234, type: 'baby-monitor', title: 'This is a title 2', description: 'this is a description 2' }
]
function ItemMethods() {
this.BannerHTML = function () {
return '<div class="banner _item_' + this.type + '_' + this.sku + '"><h2>' +
this.title + '</h2><p>' +
this.description + '</p></div>';
};
}
Items.GetBySKU = function (code) {
for (var i = 0; i < Items.length; i++) {
if (Items[i].sku == code) {
return Items[i];
}
}
};
$.each(Items, function (i, item) {
ItemMethods.apply(item);
});
alert(Items.GetBySKU(234).BannerHTML());
Any further comments or solutions gladly accepted.. always interested in potential solutions to a problem ;-)
No. There is no way to assign a different [[prototype]] of an existing object, at least according the the specification. The [[prototype]] is the object resulting from the evaluation (aka "contained in") of the constructors prototype property at time of new object creation and cannot be reassigned later. (I wish it could be officially changed, but alas it is an unsupported operation and can generally be emulated via different methods.)
Some browsers/environments may choose to expose post-creation [[prototype]] assignment with non-standard approaches. The [[prototype]] object(s) can be modified (e.g. adding to String.prototype), or singleton functions can be added to the target object (see CMS's answer), or existing objects can be wrapped (essentially a dynamic "subclass") -- depending upon requirements and restrictions.
Also, there are no "classes" in Javascript: while "classical single-inheritance objected oriented classes" can be implemented in Javascript, I find it limiting to restrict oneself to the model or use such terminology in general. A language wants to be what it is.
Happy coding.
In javascript you can create a subclass of an other by setting the subclass' prototype to an instance of the base class:
function BaseClass() {
this.baseFunction = function() {
};
};
function SubClass() {
};
SubClass.prototype = new BaseClass;
SubClass.prototype.someFunction = function() {
};
// create an instance of SubClass
var obj = new SubClass;
// SubClass truly extends BaseClass
obj instanceof BaseClass // true
obj instanceof SubClass // true
// the instance has both methods of BaseClass and SubClass
typeof obj.someFunction // Function
typeof obj.baseFunction // Function
This is the equivalent of class SubClass extends BaseClass in java.
If you also modify the prototypes after that.
If you add functions and properties to the prototype of the object's constructor, the functions and properties will be available on all the instances.
Here is an example:
function Thing (val){
this.value = val;
}
var bob = new Thing("bob");
console.log(bob.foo); // undefined
Thing.prototype.foo = function() {
console.log('foo!');
};
console.log(bob.foo); // function()
bob.foo(); // foo!
Now if you want to extend all Thing instances with Base, you can do it like this:
var base = new Base;
for (var k in base) {
Thing.prototype[k] = base[k];
}
Or if you want to make Thing instances extend Base: (i.e. don't override methods that are already in Thing)
var base = new Base;
for (var k in base) {
if (Thing.prototype[k]) continue;
Thing.prototype[k] = base[k];
}
If you only want to extend a unique object instance, just assign to it:
var bob = new Thing("bob");
var base = new Base();
bob.sayHi = base.sayHi;
bob.sayHi();
You can also call a function in the context of an object, without even assign the function to the object:
var base = new Base();
base.sayHi.call(bob);
Note that the properties that you create within the constructor, have nothing to do with the constructor's prototype, they are own properties of the object you create using new Base();, they are not inherited. However, I think what you want to do it to apply the Base constructor function on the newly created object of Thing:
function Base (){
this.sayHi = function(){
alert('hi');
}
}
function Thing (val){
Base.apply(this, arguments);
this.value = val;
}
var bob = new Thing("bob");
bob.sayHi();
Note that bob will not inherit from Base (it won't have access to properties added to Base.prototype)
bob instanceof Base; // false
bob instanceof Thing; // true
Yes.
1) You can add Base's constructor definition directly to the bob instance
Base.call(bob);
bob.sayHi(); //hi
2) Or you can augment Thing.prototype with Base's constructor definition. The bob instance can access its prototype's new properties even if it was created before they were added
var bob = new Thing("bob");
Base.call(Thing.prototype);
bob.sayHi(); //hi

Copying Javascript getters/setters to another prototype object

// Base class
var Base = function() {
this._value = 'base';
};
Base.prototype = {
constructor: Base,
// By function
getValue: function() {
return this._value;
},
// By getter
get value() {
return this._value;
}
};
// Sub class extends Base
var Sub = function() {
this._value = 'sub';
};
Sub.prototype = {
constructor: Sub
};
// Pass over methods
Sub.prototype.getValue = Base.prototype.getValue;
Sub.prototype.value = Base.prototype.value;
// ---
var mySub = new Sub();
alert(mySub.getValue()); // Returns 'sub'
alert(mySub.value); // Returns 'undefined'
At first glance it seems that mySub.value should return the same as mySub.getValue(), but as you can see it instead returns undefined. Obviously the getter is not finding the parent scope as the Sub instance (mySub), but rather a non-existent Base instance.
Is there any way around this other than having to assign the same getters onto the new prototype?
A more modern solution is to use the Object.defineProperty since it allows getters and setters to be handled without breaking them.
Only problem is that it takes a descriptor object, so instead of manually making one, use the Object.getOwnPropertyDescriptor function to just get it for you.
var BazValue = Object.getOwnPropertyDescriptor(Base.prototype,'value');
Object.defineProperty(Sub.prototype, 'value', BazValue);
Sub.prototype.__defineGetter__('value', Base.prototype.__lookupGetter__('value'));
Try that.
I think it would work if you assigned
Sub.prototype = new Base()
The issue is that the constructor is never run when you assign it directly from the Base.prototype.value. That value won't exist until you have an instance of the Base class (via new)
This is my typical method for extending Function to achieve inheritance:
Function.prototype.Extend = function(superClass) {
this.prototype = new superClass();
this.prototype.getSuperClass = function() {
return superClass;
};
this.getSuperClass = this.prototype.getSuperClass;
return this;
};
This will properly assign all of the parent classes methods and properties to the child 'class'.
Usage looks like
var Sub = function() {}
Sub.Extend(Base)
In addition to Alex Mcp's answer you could add new getters/setters to Sub after extending it using:
Function.prototype.addGetter = function(val,fn){
this.prototype.__defineGetter__(val,fn);
return this;
}
Function.prototype.addSetter = function(val,fn){
this.prototype.__defineSetter__(val,fn);
return this;
}
//example;
Sub.Extend(Base);
Sub.addGetter('date',function(){return +new Date;});
And to add to tylermwashburns answer: you could extend the Function prototype for that:
Function.prototype.copyGetterFrom = function(val,fromConstructor){
this.prototype.__defineGetter__(
val
,fromConstructor.prototype.__lookupGetter__(val));
return this;
}
//usage example.:
Sub.copyGetterFrom('value',Base);

Categories

Resources