可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
I am currently using the Chrome console to do some debugging for a Greasemonkey script.
From the console I run var opp = document.querySelectorAll('a[class="F-reset"]');
and it works as expected.
But if I try to remove the first element with opp.splice(0,1)
I get the following error
Uncaught TypeError: opp.splice is not a function at <anonymous>:2:5 at Object.InjectedScript._evaluateOn (<anonymous>:905:140) at Object.InjectedScript._evaluateAndWrap (<anonymous>:838:34) at Object.InjectedScript.evaluate (<anonymous>:694:21)
If I try to run opp[0].indexOf("a")
, i get the same thing.
How would I fix this?
回答1:
Yes, this is because the result of querySelectorAll
is a node list, not an array. You can apply the slice method of Array
to a node list, however:
Array.prototype.slice.call(op, 0, 1);
This works more or less as expected, because a NodeList
"quacks" in just the way slice
expects, i.e. it contains elements indexed sequentially. However, you should be wary of using this in general; it is much safer to simply iterate over the NodeList
.
回答2:
querySelectorAll
returns a NodeList
. This is similar to an array (it has a .length
property and you can index it with []
), but it's not actually an array, and doesn't have most of the array methods. If you want to use array methods on an array-like object, you have to call the method explicitly:
Array.prototype.splice.call(opp, 0, 1);
or:
[].splice.call(opp, 0, 1);
However, another difference between arrays and NodeLists
is that you can't modify NodeList
in place, which .splice
tries to do; you can only read them like arrays. You should just use .slice()
to extract the parts you want. Or convert the NodeList
to an array first, and then operate on that. See
Fastest way to convert JavaScript NodeList to Array?
回答3:
querySelector/All returns a NodeList not an array, so those functions are not available.
You can use call
to use those array methods though
[].splice.call(opp,0,1);
The first argument is the execution context that the function will use, all other arguments are the arguments that will be passed to the function
Function call reference
回答4:
First,
splice
is a method of Arrays, inherited through Array.prototype
, although it is intentionally generic so can be called on other Arraylike objects querySelectorAll
returns a non-live NodeList, this is not an Array and does not share any inheritance with Array, meaning you can't simply access Array methods through it - A function can be invoked with a custom
this
via call
or apply
splice
needs to be able to assign on it's this
, which will fail for a NodeList as you will get the following TypeError: Cannot set property length of #<NodeList> which has only a getter
- Other intentionally generic Array methods which only read from
this
will work on a NodeList, e.g. slice, map, indexOf, forEach, filter, some, every, etc..
Now we are in a position to do something,
- Convert the NodeList to an Array and store this reference, i.e. with
Array.prototype.slice
- Perform your
splice
on this object instead
So,
var opp = document.querySelectorAll('a[class="F-reset"]'); // NodeList oop = Array.prototype.slice.call(oop); // Array // ... oop.splice(0, 1);