Created
December 7, 2012 21:39
-
-
Save davepeck/4236746 to your computer and use it in GitHub Desktop.
ES5 properties and coffee script
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
Function::property = (prop, desc) -> | |
Object.defineProperty this.prototype, prop, desc | |
class Foo | |
@property 'neat' | |
get: -> | |
42 | |
class Bar extends Foo | |
@property 'neat' | |
get: -> | |
super | |
# 42 | |
alert(new Foo().neat) | |
# exception | |
alert(new Bar().neat) |
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
Function::property = (prop, desc) -> | |
Object.defineProperty this.prototype, prop, desc | |
class Foo | |
@property 'neat' | |
get: -> | |
42 | |
class Bar extends Foo | |
@property 'neat' | |
get: -> | |
Bar.__super__.neat | |
# 42 | |
alert(new Foo().neat) | |
# 42 | |
alert(new Bar().neat) |
The only way i found to make Bar's 'neat' work is to replace
Foo.__super__.neat
for(Object.getOwnPropertyDescriptor Bar.__super__, 'neat').get.apply @
. Not very pretty
Yep, I ended up running into this too and settled on a similar pattern. It ain't pretty, at all. Alas.
How about this?
class Person
constructor: (@firstName, @lastName) ->
@get 'fullName', -> @firstName + ' ' + @lastName
class Captain extends Person
@get 'fullName', -> 'Capt. ' + @getSuper 'fullName'
johnDoe = new Person 'John', 'Doe'
console.log johnDoe.fullName # -> "John Doe"
jackSparrow = new Captain 'Jack', 'Sparrow'
console.log jackSparrow.fullName # -> "Capt. Jack Sparrow"
# Setup
Function::get = (prop, get) ->
Object.defineProperty @prototype, prop, {get}
Function::set = (prop, set) ->
Object.defineProperty @prototype, prop, {set}
Object::getSuper = (prop) ->
(Object.getOwnPropertyDescriptor @constructor.__super__, prop).get.apply @
Object::setSuper = (prop) ->
(Object.getOwnPropertyDescriptor @constructor.__super__, prop).set.apply @
Better setup (non-enumerable)
Object.defineProperty Function.prototype, 'get', value: (prop, get) ->
Object.defineProperty @prototype, prop, {get}
Object.defineProperty Function.prototype, 'set', value: (prop, set) ->
Object.defineProperty @prototype, prop, {set}
Object.defineProperty Object.prototype, 'getSuper', value: (prop) ->
(Object.getOwnPropertyDescriptor @constructor.__super__, prop).get.apply @
Object.defineProperty Object.prototype, 'setSuper', value: (prop) ->
(Object.getOwnPropertyDescriptor @constructor.__super__, prop).set.apply @
Better setup (non-enumerable)
Object.defineProperty Function.prototype, 'get',
configurable: yes
writable: yes
value: (prop, get) ->
Object.defineProperty @prototype, prop, {get}
Object.defineProperty Function.prototype, 'set',
configurable: yes
writable: yes
value: (prop, set) ->
Object.defineProperty @prototype, prop, {set}
Object.defineProperty Object.prototype, 'getSuper',
configurable: yes
writable: yes
value: (prop) ->
(Object.getOwnPropertyDescriptor @constructor.__super__, prop).get.apply @
Object.defineProperty Object.prototype, 'setSuper',
configurable: yes
writable: yes
value: (prop) ->
(Object.getOwnPropertyDescriptor @constructor.__super__, prop).set.apply @
Hi all and thx for the example(s),
@ben-x9:
It works with setters when one changes the getter-definition
Object.defineProperty Function.prototype, 'get',
configurable: yes
writable: yes
value: (prop, get) ->
Object.defineProperty @prototype, prop, {
get: get
configurable: yes
writable: yes
}
to allow a following setter-definition. The code as-is throws 'Cannot redefine property ' in Chrome.
cheers, Andreas
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
😄
If i had to guess, i'd say that the intersection between developers who want to use getters and setters in CoffeeScript and developers that care for IE7/8 compatibility is probably pretty small. But nice consideration nevertheless.
About the second example, although it's not broken like the first one, it won't work for the general case either: if the Foo's 'neat' property depended on something stored as an own property of the instance, calling
.neat
in the superclass prototype won't work. For example:The only way i found to make Bar's 'neat' work is to replace
Foo.__super__.neat
for(Object.getOwnPropertyDescriptor Bar.__super__, 'neat').get.apply @
. Not very pretty 😅I'm not sure trying to make inheritance and getters/setters work at the same time in CS over the current semantics of JS is very plausible. ECMAScript 6 adds a lot of classical OO to the mixture, so i'd expect that having a working
super
with getters and setters over that that instead would be much much easier.