我相对较新的Javascript及其无限的伟大。我想练习为对象原型定义自己的函数,所以我练习为contains()
编写Array
函数:
if (!Array.prototype.contains){
Array.prototype.contains = function(target){
for (var i in this){
console.log(i);
if (this[i] == target) return true;
}
return false;
}
}
基本上,contains()遍历this
内的每个元素以查找target
。但是,我注意到console.log(i)
会返回索引号(即0
,1
,2
等),具体取决于元素的数量在数组内部。但是,它也总是打印出contains
!这是我的console.log
的输出,只有一个元素在数组中:
0
contains
但是,如果我改变迭代for
循环的方式,我就不会得到contains
输出:
if (!Array.prototype.contains){
Array.prototype.contains = function(target){
for (var i = 0; i < this.length; i++){
console.log(i);
if (this[i] == target) return true;
}
return false;
}
}
输出:
0
现在我已经通读了这个StackOverflow post来解释使用for... in
进行数组迭代的危险,但我不知道以编程方式解释为什么contains
是出现在我的第一个代码段中。如果我在Firefox开发人员控制台上console.log(this)
,我会按预期收到一个Array对象:
Array [ "scrubBackButton2", "scrubNextButton1" ]
数组对象的最后一个元素是否始终是使用?
调用的函数的名称我主要是通过反复试验来学习JS,所以如果我错过了一个好的答案,请务必将我推荐给好的文档或之前的帖子!
答案 0 :(得分:2)
for ... in
循环将遍历对象的每个可枚举属性。因此它将遍历['1']
属性和['2']
属性等。数组所具有的属性中有一个名为['contains']
的函数。为什么会这样?因为你把它放在那里! :)
或者更确切地说,你把它放在它的原型上。但就for ... in
而言,这几乎是一样的。它将循环遍历对象上的所有可枚举属性,以及它从其原型继承的可枚举属性,以及其原型的原型等。在Array.prototype上有很多属性,但它们不是可枚举的(这是为什么它还没有退出'推','pop','map'等)。你放在那里的那个是可枚举的,因为这是属性的默认属性。
正如您所指出的,for ... in
不适合遍历数组,因此我建议您更改代码以执行其他操作。可以是循环手册,例如this.forEach
或for ... of
。
这一行下面还有其他一些选项,但是他们会用你很少写的代码进入杂草(但是再一次,修改Array.prototype是你很少会做的事情)。
======
如果你想保留for ... in
循环,一个选项是明确检查以确保你正在查看的每个属性来自对象本身,而不是来自其原型。为此,您可以使用hasOwnProperty
。如果属性来自原型,hasOwnProperty将返回false。如果属性属于此特定对象,则返回true;
if (!Array.prototype.contains){
Array.prototype.contains = function(target){
for (var i in this){
if (!this.hasOwnProperty(i)) continue;
console.log(i);
if (this[i] == target) return true;
}
return false;
}
}
[1, 2].contains(5)
另一种可能性是使包含不可枚举。通过这样做,for ... in
循环将跳过它(Object.keys())
if (!Array.prototype.contains){
function contains(target){
for (var i in this){
console.log(i);
if (this[i] == target) return true;
}
return false;
}
Object.defineProperty(Array.prototype, 'contains', {
enumerable: false,
configurable: false,
writeable: false,
value: contains
});
}
[1, 2].contains(5);
有关定义属性的更多信息,请参阅此页面:https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/defineProperty