问题
This is one of those it seems so simple, but I cannot come up with a good way to go about it.
I have a node, maybe nodelist = document.getElementById("mydiv");
- I need to normalize this to a node list. And not an array either: an actual, bona-fide nodeList
object.
Not nodelist = [document.getElementById("mydiv")];
No libraries, please.
回答1:
Reviving this because I recently remembered something about JavaScript. This depends on how the NodeList is being checked, but..
var singleNode = (function () {
// make an empty node list to inherit from
var nodelist = document.createDocumentFragment().childNodes;
// return a function to create object formed as desired
return function (node) {
return Object.create(nodelist, {
'0': {value: node, enumerable: true},
'length': {value: 1},
'item': {
"value": function (i) {
return this[+i || 0];
},
enumerable: true
}
}); // return an object pretending to be a NodeList
};
}());
Now, if you do
var list = singleNode(document.body); // for example
list instanceof NodeList; // true
list.constructor === NodeList; // true
and list
has properties length 1
and 0 as your node, as well as anything inherited from NodeList.
If you can't use Object.create
, you could do the same except as a constructor with prototype nodelist
and set this['0'] = node;
, this['length'] = 1;
and create with new
.
回答2:
Take any element already referenced in JavaScript, give it an attribute we can find using a selector, find it as a list, remove the attribute, return the list.
function toNodeList(elm){
var list;
elm.setAttribute('wrapNodeList','');
list = document.querySelectorAll('[wrapNodeList]');
elm.removeAttribute('wrapNodeList');
return list;
}
Extended from bfavaretto's answer.
function toNodeList(elm, context){
var list, df;
context = context // context provided
|| elm.parentNode; // element's parent
if(!context && elm.ownerDocument){ // is part of a document
if(elm === elm.ownerDocument.documentElement || elm.ownerDocument.constructor.name === 'DocumentFragment'){ // is <html> or in a fragment
context = elm.ownerDocument;
}
}
if(!context){ // still no context? do David Thomas' method
df = document.createDocumentFragment();
df.appendChild(elm);
list = df.childNodes;
// df.removeChild(elm); // NodeList is live, removeChild empties it
return list;
}
// selector method
elm.setAttribute('wrapNodeList','');
list = context.querySelectorAll('[wrapNodeList]');
elm.removeAttribute('wrapNodeList');
return list;
}
There is another way to do this I thought of recently
var _NodeList = (function () {
var fragment = document.createDocumentFragment();
fragment.appendChild(document.createComment('node shadows me'));
function NodeList (node) {
this[0] = node;
};
NodeList.prototype = (function (proto) {
function F() {} // Object.create shim
F.prototype = proto;
return new F();
}(fragment.childNodes));
NodeList.prototype.item = function item(i) {
return this[+i || 0];
};
return NodeList;
}());
Now
var list = new _NodeList(document.body); // note **new**
list.constructor === NodeList; // all these are true
list instanceof NodeList;
list.length === 1;
list[0] === document.body;
list.item(0) === document.body;
回答3:
If you're targeting browsers that support document.querySelectorAll, it will always return a NodeList
. So:
var nodelist = document.querySelectorAll("#mydiv");
回答4:
var nodeList = document.createDocumentFragment();
nodeList.appendChild(document.getElementById("myDiv"));
回答5:
Yet another way to do this based on Reflect.construct: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Reflect/construct
As in other cases it requires patching NodeList.prototype.item to make calls to this function work.
NodeList.prototype.item = function item(i) {
return this[+i || 0];
};
let nl = Reflect.construct(Array, [], NodeList);
To create it with nodes pass array of nodes as second argument. This method passes checks:
list instanceof NodeList; // true
list.constructor === NodeList; // true
Array, created with it, is iterable with for..of
, forEach
and other standard methods and you can add elements into it with simple nl[n] = node;
.
来源:https://stackoverflow.com/questions/13351966/create-node-list-from-a-single-node-in-javascript