为什么在为Javascript原型定义函数时,函数名出现在for循环中?

为什么在为Javascript原型定义函数时,函数名出现在for循环中?,javascript,arrays,Javascript,Arrays,我对Javascript及其无限的伟大相对来说是个新手。我想练习为对象原型定义自己的函数,因此我练习为数组编写contains()函数: if (!Array.prototype.contains){ Array.prototype.contains = function(target){ for (var i in this){ console.log(i); if (this[i] == target) return t

我对Javascript及其无限的伟大相对来说是个新手。我想练习为对象原型定义自己的函数,因此我练习为
数组编写
contains()
函数:

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()遍历
中的每个元素以查找
目标
。但是,我注意到,
console.log(I)
根据数组中的元素数量,按预期返回索引号(即
0
1
2
,等等)。但是,它也总是打印出
包含的
!以下是我的
控制台.log的输出,数组中只有一个元素:

0
contains
但是,如果我更改迭代
for
循环的方式,则不会得到
包含的
输出:

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;
    }
}
现在我已经通读了这篇文章,解释了使用<代码>来。。。在
中使用数组迭代,但我无法以编程方式解释为什么在我的第一个代码段中出现了
包含
。如果我在Firefox开发者控制台上
console.log(this)
,我会收到预期的数组对象:

Array [ "scrubBackButton2", "scrubNextButton1" ]
数组对象的最后一个元素是否总是被调用函数的名称


我学习JS主要是通过尝试和错误,所以如果我错过了一个好的答案,请一定要参考一个好的文档或之前的so帖子

A
用于。。。在
中,循环将遍历对象的每个可枚举属性。因此,它将遍历
['1']
属性和
['2']
属性等。在数组的属性中,有一个名为
['contains']
的函数。为什么会这样?因为你把它放在那里了!:)

或者更准确地说,你把它放在原型上。但这与。。。与中的
有关。它将循环遍历对象上的所有可枚举属性,以及从其原型继承的可枚举属性,以及从其原型的原型继承的可枚举属性等。Array.prototype上有很多属性,但它们不可枚举(这就是为什么它不同时注销“push”、“pop”、“map”等)。放在那里的是可枚举的,因为这是属性的默认性质

正如您所指出的,
用于。。。in
不适合遍历数组,因此我建议更改代码以执行其他操作。可以是循环的手册,也可以是this.forEach的
,或者是。。。例如

这一行下面是一些其他选项,但它们会让您很少编写的代码陷入困境(但同样,修改Array.prototype是您很少做的事情)

========

如果您想将
保留为。。。在
循环中,一个选项是显式检查以确保您查看的每个属性都来自对象本身,而不是其原型。为此,可以使用
hasOwnProperty
。如果属性来自原型,hasOwnProperty将返回false。如果属性是此特定对象的,则返回true

if(!Array.prototype.contains){
Array.prototype.contains=函数(目标){
for(本节中的var i){
如果(!this.hasOwnProperty(i))继续;
控制台日志(i);
如果(此[i]==目标)返回true;
}
返回false;
}
}

[1,2]。包含(5)
A
,用于。。。在
中,循环将遍历对象的每个可枚举属性。因此,它将遍历
['1']
属性和
['2']
属性等。在数组的属性中,有一个名为
['contains']
的函数。为什么会这样?因为你把它放在那里了!:)

或者更准确地说,你把它放在原型上。但这与。。。与中的
有关。它将循环遍历对象上的所有可枚举属性,以及从其原型继承的可枚举属性,以及从其原型的原型继承的可枚举属性等。Array.prototype上有很多属性,但它们不可枚举(这就是为什么它不同时注销“push”、“pop”、“map”等)。放在那里的是可枚举的,因为这是属性的默认性质

正如您所指出的,
用于。。。in
不适合遍历数组,因此我建议更改代码以执行其他操作。可以是循环的手册,也可以是this.forEach的
,或者是。。。例如

这一行下面是一些其他选项,但它们会让您很少编写的代码陷入困境(但同样,修改Array.prototype是您很少做的事情)

========

如果您想将
保留为。。。在
循环中,一个选项是显式检查以确保您查看的每个属性都来自对象本身,而不是其原型。为此,可以使用
hasOwnProperty
。如果属性来自原型,hasOwnProperty将返回false。如果属性是此特定对象的,则返回true

if(!Array.prototype.contains){
Array.prototype.contains=函数(目标){
for(本节中的var i){
如果(!this.hasOwnProperty(i))继续;
控制台日志(i);
如果(此[i]==目标)返回true;
}
返回false;
}
}

[1,2]。包含(5)
很好的解释。一个问题是——为什么不鼓励修改对象的原型?这似乎是扩展功能最强大的方法之一——我也看到过一些使用原型修改作为解决方案的SO帖子,例如,如果IE的旧版本不支持indexOf()来编写自己的indexOf()…如果你是cre的话
Array [ "scrubBackButton2", "scrubNextButton1" ]