What order are knockout js observable extensions executed?

后端 未结 2 1728
长发绾君心
长发绾君心 2021-01-22 03:03

At the bottom of the knockoutjs docs for extending observables it states...

More than one extender can be applied in a single call to the .extend method of a

2条回答
  •  故里飘歌
    2021-01-22 03:21

    The order is undefined in the current Knockout (3.4.0 as of this writing), because JavaScript object properties had no defined order prior to ES2015, and even in ES2015, for-in and Object.keys have no order.

    The current Knockout loops through those extenders like this:

    function applyExtenders(requestedExtenders) {
        var target = this;
        if (requestedExtenders) {
            ko.utils.objectForEach(requestedExtenders, function(key, value) {
                var extenderHandler = ko.extenders[key];
                if (typeof extenderHandler == 'function') {
                    target = extenderHandler(target, value) || target;
                }
            });
        }
        return target;
    }
    

    Its objectForEach function uses for-in:

    function objectForEach(obj, action) {
        for (var prop in obj) {
            if (obj.hasOwnProperty(prop)) {
                action(prop, obj[prop]);
            }
        }
    }
    

    So, there is no defined order in which the extenders will run (even on ES2015) in the current Knockout.

    In theory, a future version of Knockout could use the new Object.getOwnPropertyNames instead:

    function applyExtenders(requestedExtenders) {
        var target = this;
        if (requestedExtenders) {
            Object.getOwnPropertyNames(requestedExtenders).forEach(function(key) {
                var extenderHandler = ko.extenders[key];
                if (typeof extenderHandler == 'function') {
                    target = extenderHandler(target, requestedExtenders[key]) || target;
                }
            });
        }
        return target;
    }
    

    getOwnPropertyNames respects the newly-defined order of JavaScript properties, listed in §9.1.12 of the spec. In your example, that would be required, then logChange, because object initializers create properties in lexical order, and the order of "own" properties with names that are not all-numeric and not Symbols is the order of creation (but see the spec for details).

提交回复
热议问题