knockout native vs looser bindings

JavaScript performance comparison

Test case created by Anas Nakawa

Info

difference between writing data binds as string in dom element attribute, and writing them externally in a js object

Preparation code

<script src="//ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/knockout/2.1.0/knockout-min.js"></script>

<div id="koNativeApp">
    <span data-bind="foreach: data">
        <span data-bind="text: $data"></span>
    </span>
</div>

<br /><br />

<div id="koLooserApp">
    <span data-class="loop">
        <span data-class="setText"></span>
    </span>
</div>
<script>
Benchmark.prototype.setup = function() {
    // normal app
    var koNativeData = ko.observableArray();
    var koNativeViewModel = {data: koNativeData};
   
    ko.applyBindings(koNativeViewModel, document.getElementById('koNativeApp'));
   
    var koNativeClear = function (){
        koNativeData.splice(0, koNativeData().length);
    };
   
    var koNativePush = function (data){
        koNativeData.push(data);
    };
   
    // looser data binding app
    var customBindingProvider = function (bindingObject) {
        this.bindingObject = bindingObject;
        //determine if an element has any bindings
        this.nodeHasBindings = function (node) {
            return node.getAttribute ? node.getAttribute("data-class") : false;
        };
        // return the bindings given a node and the bindingContext
        this.getBindings = function (node, bindingContext) {
            var result = {};
            var classes = node.getAttribute( "data-class" );
            if (classes) {
                classes = classes.split(' ');
                //evaluate each class, build a single object to return
                for (var i = 0, j = classes.length; i < j; i++) {
                    var bindingAccessor = this.bindingObject[classes[i]];
                    if (bindingAccessor) {
                        var binding = typeof bindingAccessor == "function" ? bindingAccessor.call(bindingContext.$data) : bindingAccessor;
                        $.extend(result, binding);
                    }
                }
            }
            return result;
        };
    };
   
    var koLooserData = ko.observableArray();
    var koLooserViewModel = {data: koLooserData};
   
    var koLooserBindings = {
        'loop': { foreach: koLooserViewModel.data },
        'setText': function() { return { text: this }; }
    };
   
    ko.bindingProvider.instance = new customBindingProvider(koLooserBindings);
   
    ko.applyBindings(koLooserViewModel, document.getElementById('koLooserApp'));
   
    var koLooserClear = function (){
        koLooserData.splice(0, koLooserData().length);
    };
   
    var koLooserPush = function (data){
        koLooserData.push(data);
    };
   
   
};
</script>

Preparation code output



Test runner

Warning! For accurate results, please disable Firebug before running the tests. (Why?)

Java applet disabled.

Testing in unknown unknown
Test Ops/sec
Native Data Bindings
koNativeClear();
for (var i = 0; i < 100; i++)
  koNativePush("koNative");
pending…
Looser Data Binding
koLooserClear();
for (var i = 0; i < 100; i++)
  koLooserPush("koLooser");
pending…

You can edit these tests or add even more tests to this page by appending /edit to the URL.

Compare results of other browsers

0 comments

Add a comment