Implementing Mixins in JavaScript

an article added by: Sonja Lande at 05312007


In: Categories » » AJAX » Implementing Mixins in JavaScript

Problem You want to implement Ruby-style mixins in JavaScript to easily extend object functionality. Theory In Ruby, mixins are a way of extending the functionality of an object by adopting the functionality of another object. When you instantiate a JavaScript type, the methods and properties associated with the type depend on the declaration of the type. To extend the functionality of an instance, a property is assigned with a function or another object.

   Source: /website/ROOT/ajax articles/javascript/mixins.html
   function DefinedClass() {
   }
   DefinedClass.prototype.defined1 = function() {  }
   DefinedClass.prototype.defined2 = function() {  }

The DefinedClass function is used to define a type. Two methods, defined1 and defined2, are associated with the DefinedClass type. Each method is associated with the prototype property, so every time DefinedClass is instantiated, these methods will share the same function instance. Thus, if you assign a property of defined1 or defined2, then all instances of DefinedClass will be able to share the same property instance. Solution To extend an instance of DefinedClass, you could individually assign the properties of the instance. Individually copying a property is tedious; a more efficient solution is to copy the properties of one object to another object. Many frameworks, such as Prototype and Dojo Toolkit, provide the ability to copy properties. Following is the mixin implementation for Prototype.

   Source: /website/ROOT/prototype/dist/prototype.js
   Object.extend = function(destination, source) {
   for (property in source) {
   destination[property] = source[property];
   }
   return destination;

The Object.extend function has two parameters: destination and source. The destination parameter represents an object that will have properties added. The source parameter represents an object that will have its properties copied. The properties are copied using a for loop because it is not possible to iterate the properties of an object instance in any other way. The property identifier, not the property value, is iterated. To retrieve the property value, you could use the following syntax: source.property The problem with this notation is that the property is defined explicitly, and using it in the context of implementing a mixin function is complicated. The solution is to use the JavaScript array notation and retrieve the property as an array. Going back to the Prototype solution, as each property of the source is iterated, the value is retrieved and assigned to the destination. Let’s apply the extend method using the following object instance declaration.

   Source: /website/ROOT/ajax articles/javascript/mixins.html
   MyExtensions = {
   test : function(tstValue) {
   assertEquals(tstValue,  MyExtensions.test.value);
   }
   }

The MyExtensions class declaration is a static reference to a single embedded property that is an instance of type Object. We want to copy the property to an instance of DefinedClass, as shown in the following test.

   Source: /website/ROOT/ajax articles/javascript/mixins.html
   prototype_mixin : function() {
   var cls = new DefinedClass();
   if( MyExtensions.test.value) {
   testManager.failed();
   }
   Object.extend(cls, MyExtensions);
   cls.test.value = 3;
   cls.test(3);
   cls.test.value = 10;
   cls.test(10);
   },

The test code goes beyond the simple calling of Object.extend, but reveals that most toolkits implement mixins using duck types based on references. It is not wrong, but because functions are objects they will be shared among multiple class types. To understand this, look at the implementation of MyExtensions.test. The implementation references the test.value function property and cross-references it with the tstValue parameter. In the implementation of the prototype_mixin function, an instance of DefinedClass is created and then extended with the methods of MyExtensions. The cls.test.value property is assigned a value of 3, and the test method is called.

The implementation of test verifies the value of MyExtensions.test.value as 3. If the test method of cls were a copy of the MyExtension.test method, then the test would fail because MyExtensions.test.value has not been assigned, as evidenced by the if test block. But the test code does not fail, which indicates that cls.test and MyExtensions.test are one and the same method. Referenced-based duck typing has some odd behaviors, one of which is shown in the following code.

   Source: /website/ROOT/ajax articles/javascript/mixins.html
   function GetExtensionFunctionality() {
   return {
   test : function(tstValue) {
   assertEquals(tstValue, this.test.value);
   }
   }
   }
   prototype_inconsistent_mixin : function() {
   var cls1 = new DefinedClass();
   var cls2 = new DefinedClass();
   Object.extend( cls1, GetExtensionFunctionality());
   Object.extend( cls2,  GetExtensionFunctionality());
   cls1.test.value = 3;
   try {
   cls2.test( 3);
   }
   catch( e) {
   if (e.jsUnitMessage) {
   info("prototype_inconsistent_mixin",  "Expected exception
   (" + e.jsUnitMessage + ")");
   }
   }
   },

Here, the extended functionality is defined in the context of a method call. In the previous example, the test method was shared by multiple classes. In the test, cls1 and cls2 should also share the same test method. Running the test code will result in an expected exception stating that cls.test.value does not have the value 3. In a nutshell, the problem is that you have two ways of calling Object.extend, and you get two completely different behaviors due to the nature of value- and reference-based duck typing. It is something that you need to be aware of, because you might get some odd behavior. Of course, a counterargument could be that if you think about the nature of the prototype property, the same sort of behavior results. I agree that is the case but also realize that the examples did not use the prototype identifier. A JavaScript developer knows what the ramifications of prototype are, and thus will know when to use and when not to use the keyword. In this article’s examples, a prototype behavior was illustrated without using prototype. We know about this situation and have two mixin methods: one that copies references (reference duck typing) and one that does a complete copy (value duck typing). The complete value-based duck-typed mixin implementation follows.

   Source: /website/ROOT/scripts/jaxson/common.js
   mixin : function( copyTo, copyFrom, forceCopy)  {
   var  copiedFrom = eval( ops.singleSerialize( copyFrom));
   for (property in copyFrom) {
   if((copyTo[ property] && force) ||  !copyTo[ property]) {
   copyTo[ property] = copiedFrom[ property];
   }
   }
   }

In the implementation of the mixin method, the first step is to generate a buffer of the instance to be copied (ops.singleSerialize), and then execute the buffer using eval. The process of generating a buffer and then executing it has the effect of cloning the object and its properties. Then when the clone is iterated, the object to be extended has references to the cloned object, and not the original object. This fulfills the requirement that the object to be extended has copied the properties of the source object.

In the article’s source code, you’ll also find a method called ops.refMixin, which behaves like the other mixin implementations and assigns references to the object to be extended. When implementing mixins, keep the following points in mind:

• Mixins are a way of extending the functionality of an object by adopting the functionality of another object. In JavaScript, you can replicate this technique by copying the references or by copying the functionality directly.

• Mixins are a form of prototype-based programming where the behavior of the object is determined at runtime.

• You may not write properties that are part of functions, and thus think that the reference copying is not a problem. But be forewarned: if your source object references properties that reference objects, then the object is not copied, but rather the reference to the object.

• You will use mixins extensively when writing JavaScript code, so be careful with your objects and references.

legal notice

Our website is not responsible for the information contained by this article. Web-articles is a free articles resource.
Suggestion: If you need fresh, daily updated content for your website, feel free to use our service. Click here for more information.

Useful tools and features

Link to this article from your page    Send this article to you or to a friend
If you like this article (tutorial), please link to it from your web page using the information above.

related articles

1. The Easiest Way to Get Started with Ajax and REST
The Easiest Way to Get Started with Ajax and REST Problem You want to know the best way to get started with writing Ajax and REST. Solution When developing an Ajax and REST application, you must decide on the tools and frameworks you’ll use. The choice is simple: Use whatever you’re using today, and write some Ajax applications. You don’t need to change the tools you’re using today. Whether you’re using ASP.NET, JavaServer Pages (JSP), PHP, Ruby, or Python, you...

2. Testing a Dynamic Contract with Ajax
Coding the Contract Using Test-Driven Development Techniques Coding the contract using agile and test-driven development techniques requires writing a number of tests and implementing aMock URL layer. Problem You want to code the contract using these development techniques. Solution To demonstrate, let’s define a use case, implement the use case as a contract, write a test case(s) to implement the contract, implement the contract in the Mock URL, and finally...

3. Testing the Client Side Logic
Problem You want to effectively test your application’s client-side logic. Theory Testing GUI code tends not to be a productive task because of the complications that arise. The main complication is how to test the correctness of a user interface. Imagine a situation where clicking a button causes a table to be filled with data. Now imagine that when a check box is checked and the button is clicked again, a different table is filled with content. The fact that clicking the same button results in two ...

4. Understanding JavaScript and Types
Understanding JavaScript and Types Problem You want to work around the fact that JavaScript does not have types declared for its variables. Theory JavaScript code does not have any variables with a declared type. The lack of typed variables is apparent when you declare functions. That said, not having typed variable declarations does not mean JavaScript has no types or no type safety. Let’s start out with the simple declaration of a function, as illustrated by the following ex...

5. Coding Using Conventions and Not Configurations
Coding Using Conventions and Not Configurations Problem You want to make your JavaScript constructs more efficient by applying the Rails “convention over configuration” principle to them. Theory You may already be familiar with the programming platform Ruby on Rails, which is used to build Web applications. The focus of this recipe is not Ruby on Rails, but one aspect of Ruby on Rails namely, convention over configuration (see http://en.wikipedia.org/wiki/ Ruby_on_Rails for m...

6. Advantage of parameterless functions in JavaScript
Using Parameterless Functions Problem You want to take advantage of parameterless functions in JavaScript. Theory JavaScript functions for the most part have parameters. You may think that the previous sentence states the obvious after all, without parameters, what data could be passed to a function? JavaScript has the ability to declare functions that have no parameters, even though the caller of the function has passed parameters to the function. For example, let’s look at...

7. JavaScripot Functions
Treating Functions Like Objects Problem You want to take advantage of the fact that functions are objects (remember, everything is an object in JavaScript). Theory Many people think that a function is some keyword used in JavaScript. A function is also an object that can be manipulated. Knowing that a function is an object makes it very interesting from the perspective of writing JavaScript code, because the code can treat the function like another other object. This mean...