Protocol: SC.ObjectMixinProtocol
The SC.ObjectMixinProtocol
protocol defines the properties and methods that you may implement
in your mixin objects (i.e. JavaScript Objects passed to SC.Object's
extend
or create
) in
order to access additional functionality when used. They will be used if defined but are not
required.
What is a Mixin?
A mixin, in this context, is a simple JavaScript Object that can be used to provide extra
functionality to SC.Object
subclasses. While you can mix JavaScript Objects into "classes" (i.e.
using SC.mixin(SomeClass)
), this particular protocol only refers to mixins in the context of
use with an SC.Object
"instance" (i.e. SC.Object.create(
{ ... })).
For example, in order to share a method between two different classes of object, we can use a mixin object that both will consume,
// Common default properties and shared methods which our different classes may consume.
MyApp.MyMixin = {
a: true,
aFunc: function () {
this.set('a', false);
},
b: [], // SHARED OBJECT!
c: {} // SHARED OBJECT!
};
// Two different object types, which both need the functionality provided by MyApp.MyMixin.
MyApp.ObjectType1 = SC.Object.extend(MyApp.MyMixin);
MyApp.ObjectType2 = SC.Object.extend();
obj1 = MyApp.ObjectType1.create();
obj2 = MyApp.ObjectType2.create(MyApp.MyMixin);
// Some proofs.
// 1. The default properties are copied over to the new objects.
obj1.get('a'); // true <--
obj2.get('a'); // true <--
// 2. The primitive properties are unique to each object.
obj1.set('a', false);
obj1.get('a'); // false <--
obj2.get('a'); // true <--
// 3. The methods are copied over to the new objects.
obj1.aFunc; // function () { ... } <--
obj2.aFunc; // function () { ... } <--
// 4. The functions/objects are shared between objects.
obj1.aFunc === MyApp.MyMixin.aFunc; // true <--
obj1.aFunc === obj2.aFunc; // true <--
obj1.b === obj2.b; // true <-- !! Beware of modifying this object !!
obj1.c === obj2.c; // true <-- !! Beware of modifying this object !!
In this example, we used a mixin to share functionality between two classes, which is very easily achieved. There is one issue, that has been known to trip up developers, which should be highlighted. If you set default Objects (e.g. [] or {}) in a mixin, these same Objects will be shared between all of the mixin's consumers.
If you want to set a default Object that is unique to each consumer of the mixin, a better
practice is to set it in initMixin()
or to check for its existence the first time it is used
and only create it then.
Note: Do not mix SC.ObjectMixinProtocol
into your classes. As a protocol, it exists only for
reference sake. You only need define any of the properties or methods listed below in order to use
this protocol.*
Defined in: mixin_protocol.js
Class Methods
Class Method Detail
This optional method is called to further de-initialize the consumer of the mixin when it is
destroyed. When a mixin (i.e. JavaScript Object) is used to extend an SC.Object
subclass, we
may want to perform additional teardown of the SC.Object
instance when it is destroyed
according to the needs of the mixin (e.g. to clean up objects that the mixin code initialized
and that may otherwise lead to memory leaks). In order to support this, SC.Object
will call
this method, destroyMixin
, if implemented, on each mixin in the order that they were
initially added.
For example, if we use two mixins that both de-initialize the same value, the last mixin added would win,
myObject = SC.Object.create(
// Mixin.
{
initMixin: function () {
// Created extra object for some purpose.
this.set('anObject', SC.Object.create());
},
destroyMixin: function () {
// Clean up extra object that the mixin is responsible for.
var anObject = this.get('anObject');
anObject.destroy();
this.set('anObject', null);
}
});
myObject.get('a'); // false <--
Note, that unlike the similar destroy()
method of SC.Object
, you do not need to call
sc_super
in destroyMixin
.
This optional method is called to further initialize the consumer of the mixin when it is
created. When a mixin (i.e. JavaScript Object) is used to extend an SC.Object
subclass, we may
want to perform additional set up of the SC.Object
instance when it is created according to
the needs of the mixin. In order to support this, SC.Object
will call this method,
initMixin
, if implemented, on each mixin in the order that they were added.
For example, if we use two mixins that both initialize the same value, the last mixin added would win,
myObject = SC.Object.create(
// First mixin.
{
initMixin: function () {
this.set('a', true);
}
},
// Second mixin.
{
initMixin: function () {
this.set('a', false);
}
});
myObject.get('a'); // false <--
This was just an example to illustrate the order in which initMixin
is called. It is rare
that mixins will collide with each other, but it is something to bear in mind when making heavy
use of mixins.
Note, that unlike the similar init()
method of SC.Object
, you do not need to call
sc_super
in initMixin
.