Description
From: canjs/canjs#2441
This proposal seeks to formalize the behavior of "looping" DefineMap methods and JavaScript functions and statements in relationship to the serialize
, get
and a new enumerable
behavior.
Methods, functions, and statements
This proposal attempts to define the behavior of the following DefineMap methods, JavaScript functions, and JavaScript statements:
.get()
- gets a non-observable representation of this map..serialize()
- gets the POJO form of this map.for...in
- Can control in limited fashion.Object.keys()
.hasOwnProperty()
.getOwnPropertyNames()
in
operator
Note that JavaScript does not provide a mechanism to control the following behaviors:
Object.keys()
- Would need[OwnPropertyKeys]
symbol here..hasOwnProperty()
- Would need[OwnPropertyKeys]
symbol..getOwnPropertyNames()
- Would need[OwnPropertyKeys]
symbol.
In these cases, this proposal provides a desired behavior. The actual behavior will probably not work that way and a can-define
alternative will need to exist.
for...of
can be controlled with Symbol.iterator.
define behaviors
I propose two behaviors for controlling the previously listed methods, functions, and statements.
- enumerable
Boolean
- true if the property is enumerable, false if otherwise.getters
areenumerable: false
by default, all other properties areenumerable: true
by default. - serialize
Boolean | function()
- Controls the behavior of onlyserialize
, overwrites the behavior ofenumerable
.
Furthermore, all core JavaScript functions and statements should follow the .get()
behavior:
for...in
- Same asfor(var prop in map.get())
Object.keys()
- Same asObject.keys( map.get() )
.hasOwnProperty()
- Same asmap.get().hasOwnProperty( propName )
.getOwnPropertyNames()
- Same asmap.get().getOwnPropertyNames()
in
operator - Same asprop in map.get()
Examples
enumerable: undefined
enumerable: undefined
Type = DefineMap.extend({ prop: {} })
var map = new Type({prop: "VALUE"});
.get() //-> {prop: "VALUE"}
.serialize() //-> {prop: "VALUE"};
enumerable: undefined, serialize: false
for #100
Type = DefineMap.extend({ prop: {serialize: false} })
var map = new Type({prop: "VALUE"});
.get() //-> {prop: "VALUE"}
.serialize() //-> {};
enumerable: false
enumerable: false
Type = DefineMap.extend({ prop: {enumerable: false} })
var map = new Type({prop: "VALUE"});
.get() //-> {}
.serialize() //-> {};
enumerable: false, serialize: true
Type = DefineMap.extend({ prop: {serialize: true, enumerable: false} })
var map = new Type({prop: "VALUE"});
.get() //-> {}
.serialize() //-> {prop: "VALUE"};
enumerable: true
enumerable: true
Type = DefineMap.extend({ prop: {enumerable: true} })
var map = new Type({prop: "VALUE"});
.get() //-> {prop: "VALUE"}
.serialize() //-> {prop: "VALUE"};
enumerable: true, serialize: false
Type = DefineMap.extend({ prop: {serialize: false, enumerable: true} })
var map = new Type({prop: "VALUE"});
.get() //-> {prop: "VALUE"}
.serialize() //-> {};
Big example
propA: {enumerable: undefined, serialize: undefined}, //-> get, serialize
propB: {enumerable: undefined, serialize: undefined, get: getter} //-> !get, !serialize
propA: {enumerable: undefined, serialize: true} //-> get, serialize
propB: {enumerable: undefined, serialize: true, get: getter} //-> !get, serialize
propA: {enumerable: undefined, serialize: false} //-> get, !serialize
propB: {enumerable: undefined, serialize: false, get: getter} //-> !get, !serialize
propA: {enumerable: true, serialize: undefined} //-> get, serialize
propB: {enumerable: true, serialize: undefined, get: getter} //-> get, serialize
propB: {enumerable: true, serialize: true, get: getter} //-> get, serialize
propB: {enumerable: true, serialize: true} //-> get, serialize
propA: {enumerable: false, serialize: undefined} //-> !get, !serialize
propB: {enumerable: false, serialize: undefined, get: getter} //-> !get, !serialize
propB: {enumerable: false, serialize: true, get: getter} //-> !get, serialize
propB: {enumerable: false, serialize: true} //-> !get, serialize