I would like to programmatically access the string representation of an evaluator function definition of a KO computed field. For example, in the case of:
self.field = ko.computed(function () {
return 'HELLO WORLD';
});
I would like to retrieve the string:
"function () {
return 'HELLO WORLD';
}"
I've tried several things with Object.keys()
and JSON.stringify()
but I can't seem to get to the function definition.
The source code for ko.computed
seems to try its best to hide this from consumers.
if (DEBUG) {
// #1731 - Aid debugging by exposing the computed's options
computedObservable["_options"] = options;
}
Symbol
:var computedState = ko.utils.createSymbolOrString('_state');
// ...
computedObservable[computedState] = state;
If you're willing to either:
debug
version of knockout, orko.computed
in a custom constructor between ko's initialization & the first external calls to it, orSymbol
from global this / use a browser that does not support symbols, (see here)you can still make things work.
My preferred option here would be option 2. See the interactive snippets below for some proofs of concept of each approach.
const msg = ko.observable("Hello world");
const computedWithDependencies = ko.computed(function() {
return msg();
});
const computedWithoutDependencies = ko.computed(function() {
return "Hello world";
});
console.log(computedWithDependencies._state.readFunction);
console.log(computedWithDependencies._options.read.toString());
// This one won't work because ko auto disposes the computed
console.log(computedWithoutDependencies._state.readFunction);
console.log(computedWithoutDependencies._options.read.toString());
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.5.1/knockout-latest.debug.js"></script>
ko.computed
const ogComputed = ko.computed;
ko.computed = function(f) {
// TODO: support other argument signatures like `options` and `context`
const c = ogComputed(f);
c._exposed = f;
return c;
}
const myComputed = ko.computed(function() {
return "Hello world";
});
console.log(myComputed._exposed.toString());
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.5.1/knockout-latest.min.js"></script>
const msg = ko.observable("Hello world");
const c = ko.computed(function() {
return msg();
});
// The read function should be the only function in state...
console.log(Object.values(c._state).find(f => typeof f === "function").toString());
<script>
window._Symbol = Symbol;
window.Symbol = undefined;
</script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.5.1/knockout-latest.min.js"></script>
<script>
window.Symbol = window._Symbol;
delete window._Symbol;
</script>