Skip to content

WebReflection/define-strict-properties

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

17 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

define-strict-properties

defining types in JavaScript via ES5 compatible descriptors

build status

Object.create(proto, typedProperties)

Following all goals of this project:

  • zero performance impact, all you have to do is to not include the main file in production
  • fully ES5 backward compatible, it works with ES5 descriptors already in your code, nothing to change
  • methods and signatures overload, you can accept one or more arguments and of different type, just specify them
  • multiple returns type, you can return one or more variable type
  • no syntax changes, which means no broken JavaScript, no need for transpilers, no need for source maps, no need for ... you name it, it's just vanilla JavaScript with the ability to specify types via descriptors!

As extra ideal goal, JS documentation tools could use these descriptors to simplify the generation of the documentation per each class structure.

Moreover, as virtual ideal goal bonus, JavaScript engines could follow this proposal to boost up performance via typed properties, in a similar way property access is planned to be optimized in Typed Object anyway, except this proposal is also suitable for runtime operations instead of static shapes only.

Last but not least, this project could also be used to actually implement StructType polyfills for ES5 compatible engines.

Compatibility

Every engine that is compatible with ES5 specifications, including:

  • IE9+, and IEMobile 9+
  • Firefox Desktop, Mobile, and Firefox OS
  • any Webkit based browser (Safari, Android 2+, iOS 5+, Kindle Silk, Blackberry, PhantomJS, webOS, etc)
  • any Chrome and Mobile Chrome,
  • any Opera 12+ plus mobile and mini
  • nodejs, Rhino, DynJS, I believe any updated server side JS engine too

To check if your browser supports this script without extra polyfills, feel free to check the test page

Regular ES5 Descriptors

ES5 descriptors are objects usually created at runtime able to define properties in a powerful way. Following a quick summary about ES5 descriptors:

Object.defineProperty(genericObject, {

  // will it show up in for/in or in Object.keys() ?
  enumerable: true,   // false by default
  // is it possible to redefine this value 
  // using Object.defineProperty again ?
  configurable: true, // false by default


  // defining property directly

  // specify if the value can change at runtime
  writable: true,     // false by default
  // the property value
  value: any,


  // defining property via getters/setters
  // (no writable allowed by specs)

  // the getter, returns anything, even methods
  get: function () {
    return any;
  },

  // the setter, will receive the set value
  // obj.prop = anyValue;
  set: function (anyValue) {
    any = anyValue;
  }

});

Enriched ES5 Descriptors

If you include define-strict-properties before other scripts in your development environment, you'll be able to do more with descriptors preserving native ES5 behavior.

Types

These are the types that work exactly the same when specified as arguments, returns, or type fields in the descriptor.

  • "boolean", as typeof obj === 'boolean'
  • "function", as typeof obj === 'function'
  • "number", as typeof obj === 'number'
  • "object", as typeof obj === 'object', including null, no surprises here, is still JS as it is
  • "string", as typeof obj === 'string'
  • "undefined", as typeof obj === 'undefined', it looks pointless but it can actually become handy if there is some property that should be flagged as reserved and accessing it should throw an error
  • "any", as any kind of value, it will accept really anything, basically a white flag for the typeof filter
  • Constructor, validated as obj instanceof Constructor
  • genericObject, validated as genericObject.isPrototypeOf(obj), particularly handy if you use Object.create(fromObject) instead of constructors for new objects instead of classes

Following few examples on how to use them.

Typed Value

// basic descriptor example
Object.defineProperty(genericObject, {
  type: 'number',
  writable: true,
  value: 123
});

// via multiple descriptors
var typed = Object.create(null, {
  method: {
    type: 'function',
    writable: true,
    value: function () {
      // it can be changed even later on
      // with another method
    }
    // keep reading for arguments
    // and returns type
  },
  property: {
    type: 'string',
    value: 'Hello There!'
  },
  instance: {
    type: HTMLElement,
    value: document.createElement('canvas')
  },
  proto: {
    type: someObjectThatIsPrototypeOf,
    value: anotherOne
  }
});

Methods arguments

function Person(name) {
  this.name = name;
}

Object.defineProperties(
  Person.prototype, {

  // properties
  // easy to ensure types
  title: {
    writable: true,
    type: 'string',
    value: '' // as default
  },
  age: {
    writable: true,
    type: 'number',
    value: 0
  },
  name: {
    writable: true,
    type: 'string'
  },

  // methods are easily
  // ensured by default as not enumerable
  // not configurable and not writable
  // so that is not possible to change
  // them during a class lifecycle
  // and this is normal ES5 behavior ;-)
  promoteTo: {
    // only one argument, as string
    arguments: ['string'],
    value: function (title) {
      this.title = title + ' ';
    }
  },

  toString: {
    returns: ['string'],
    value: function () {
      return this.title + this.name;
    }
  }

});

var me = new Person('Andrea');
me.promoteTo('Mr');
me.age = 35;
console.log('' + me); // Mr Andrea

License

A classic MIT Style License

About

No description, website, or topics provided.

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published