    /** * This class is the base for `Binding` and `MultiBinding`. * @private */Ext.define('Ext.app.bind.BaseBinding', {    extend: 'Ext.util.Schedulable',     calls: 0,     kind: 20,     defaultOptions: {},     lastValue: undefined,     /**     * @cfg {Boolean} [single=false]     * This option instructs the binding to call its `destroy` method immediately after     * delivering the initial value.     * @since 5.0.0     */     constructor: function (owner, callback, scope, options) {        var me = this;         me.options = options;        me.owner = owner;        me.scope = scope;        me.callback = callback;         //<debug>         if (!callback) {            Ext.raise('Callback is required');        }        //</debug>          // If given a string callback name, preserve the late binding:         me.lateBound = Ext.isString(callback);        if (options && options.deep) {            me.deep = true;        }         me.callParent();    },     destroy: function () {        var me = this,            owner = me.owner;         if (owner) {            owner.onBindDestroy(me);        }         me.callParent();                me.scope = me.callback = me.owner = null;    },     isReadOnly: function() {        return true;    },     privates: {        getScheduler: function () {            var owner = this.owner;            return owner && owner.getScheduler();        },         getSession: function () {            var owner = this.owner;            return owner.isSession ? owner : owner.getSession();        },         notify: function (value) {            var me = this,                options = me.options || me.defaultOptions,                previous = me.lastValue;             // We want to deliver if:             // 1) We've never been called             // 2) We're a deep binding, which means that our object reference may not have changed,             //    but something under us has changed. For example a link stub or a model field binding             // 3) If the value has changed             // 4) If the value is an array. It's difficult to tell if the underlying data changed             if (!me.calls || me.deep || me.valueChanged(value, previous)) {                ++me.calls;                me.lastValue = value;                 if (me.lateBound) {                    // Interestingly, lateBound-ness may be more efficient since it does                     // not use the "call" method.                     me.scope[me.callback](value, previous, me);                } else {                    me.callback.call(me.scope, value, previous, me);                }                 if (options.single) {                    me.destroy();                }            }        },         valueChanged: function(value, previous) {            var ret = true;             if (previous !== value) {                if (value && previous && value instanceof Date && previous instanceof Date) {                    ret = value.getTime() !== previous.getTime();                }            } else {                ret = Ext.isArray(value);            }            return ret;        }    }});