this似乎显示了完整的方法列表。
显然找到解决方法并不困难......但为了优雅,应该有一种方法isConnected
,不应该在那里吗?
答案 0 :(得分:1)
如果您真的想知道MutationObserver对象实例的状态,那么一种实现方法就是以合成样式(JSFiddle example)从它创建一个新的对象类:
// to keep actual working methods of the class out of the object's instance whenever possible
// is a good practice, but since ECMAScript2015 (ES2015, ES6) does not support private methods
// (though does support private variables with "var" in constructors), IIFE (Immediately-invoked
// function expression) has to be used to encapsulate, isolate the full class definition:
let UpgradedMutationObserver = (function()
{
// private variable/property to store the instance's current status; WeakMap is used to improve memory
// management as it sheds its value pairs as soon as the instance is not reference any more:
const _targetsArrayWeakMap = new WeakMap(), // new WeakMap([[this, []]]) would not work as "this" here is a window object
// private method-function wrapper that provides access for the object's instance to class prototype
// methods as well as to an earlier-declared private variable;
// this wrapper is designed as a function factory as it returns functions that get assigned to the object
// instance's public methods:
_callPrototypeMethod = function(prototypeMethod, instance, args)
{
// actual type of the private variable/property is set here; runs only once:
if (typeof _targetsArrayWeakMap.get(instance) === 'undefined')
{
_targetsArrayWeakMap.set(instance, []);
}
return function()
{
const returnedObject = Object.getPrototypeOf(instance)[prototypeMethod](instance, _targetsArrayWeakMap.get(instance), ...arguments);
_targetsArrayWeakMap.set(instance, returnedObject.privateVariable);
return returnedObject.returnValue;
}
};
class UpgradedMutationObserver
{
constructor(callback)
{
// an arrow function version of the way to attach the object's instance would not need .bind(this)
// as there is no own "this" in arrow functions, "this" would mean the instance of the object
this.MutationObserver = new MutationObserver(function( ...args)
{
return callback( ...args, this);
}.bind(this));
this.observe = _callPrototypeMethod('observe', this, arguments); // bind(this);
this.disconnect = _callPrototypeMethod('disconnect', this, arguments); //.bind(this);
this.isConnected = _callPrototypeMethod('isConnected', this, arguments); //.bind(this);
// ... other standard methods like takeRecords() can also taken care of, if necessary
}
observe(instance, targetsArray, targetObserve, optionsObserve)
{
// many targets can be observed, though callback function is always the same
// for the same instance of (Upgraded)MutationObserver:
instance.MutationObserver.observe(targetObserve, optionsObserve);
// before adding targetObserve to the list of observed,
// it is checked that it exists (at least for now):
if (document.contains(targetObserve))
{
targetsArray.push(targetObserve);
}
return {privateVariable: targetsArray};
}
disconnect(instance, targetsArray)
{
// the method stops observation of all targets at once
instance.MutationObserver.disconnect();
targetsArray = [];
return {privateVariable: targetsArray};
}
isConnected(instance, targetsArray, targetToCheck)
{
// in case of observed nodes removed from DOM (destroyed), they are filtered out:
targetsArray = targetsArray.filter(function(e)
{
return document.contains(e);
});
// maximum versatily of return results is provided
// all while maintaining false/"truthy" quasi-boolean dichotomy:
return {
privateVariable: targetsArray,
returnValue: targetsArray.length == 0
? false
: (targetToCheck
? targetsArray.includes(targetToCheck)
: targetsArray)
};
}
}
return UpgradedMutationObserver;
})();
console.log('UpgradedMutationObserver: ____________________________________________________________');
const observer = new UpgradedMutationObserver(function(mutationsList, observer)
{
console.log('UpgradedMutationObserver callback: processing of an added node', mutationsList, observer);
});
console.log('UpgradedMutationObserver initialized as "observer": ', observer);
console.log('UpgradedMutationObserver: observer.isConnected(): ', observer.isConnected());
console.log('UpgradedMutationObserver: observer.observe(document.documentElement, {childList: true, subtree: true})...');
observer.observe(document.documentElement, {childList: true, subtree: true});
// logs "Array [ html....]"
console.log('UpgradedMutationObserver: observer.isConnected(): ', observer.isConnected());
console.log('UpgradedMutationObserver: observer.observe(document.body, {childList: true, subtree: true})...');
observer.observe(document.body, {childList: true, subtree: false});
// logs "Array [ html. ..., body. ...]"
console.log('UpgradedMutationObserver: observer.isConnected(): ', observer.isConnected());
// logs "true":
console.log('UpgradedMutationObserver: observer.isConnected(document.documentElement): ', observer.isConnected(document.documentElement));
var div = document.querySelector('div'), childDiv, i;
for (i = 1; i < 5; i++)
{
setTimeout(function()
{
if (this < 4)
{
childDiv = document.createElement('div');
div.appendChild(childDiv);
console.log("a child DIV is added after " + this + "s delay for UpgradedMutationObserver to discover");
}
else
{
console.log('UpgradedMutationObserver: observer.disconnect()...');
observer.disconnect();
// logs "false" as nothing is observed:
console.log('UpgradedMutationObserver: observer.isConnected(): ', observer.isConnected());
}
}.bind(i), i * 1000);
}