无法理解Javascript Koans中的反射测试

Sea*_*lsh 5 javascript reflection

已经有一个答案发布到测试本身,可以在这里找到,但我似乎无法弄清楚为什么答案是正确的.

给我带来麻烦的部分测试是:

var keys = [];
var fruits =  ['apple', 'orange'];
for(propertyName in fruits) {
    keys.push(propertyName);
}
ok(keys.equalTo(['__', '__', '__']), 'what are the properties of the array?');
Run Code Online (Sandbox Code Playgroud)

如上所述的那个(显然)正确的答案是

ok(keys.equalTo(['0', '1', 'fruits.prototype'), 'what are the properties of the array?');
Run Code Online (Sandbox Code Playgroud)

我尝试插入答案 - 修复了语法错误 - 我的测试仍然失败.

在同一个测试文件中,另一个测试几乎相同,答案是我所期望的:

test("property enumeration", function() {
    var keys = [];
    var values = [];
    var person = {name: 'Amory Blaine', age: 102, unemployed: true};
    for(propertyName in person) {
        keys.push(propertyName);
        values.push(person[propertyName]);
    }
    ok(keys.equalTo(['name','age','unemployed']), 'what are the property names of the object?');
    ok(values.equalTo(['Amory Blaine',102,true]), 'what are the property values of the object?');
});
Run Code Online (Sandbox Code Playgroud)

我可以在这两个测试之间看到的唯一区别是第二个是使用对象而不是数组.

我从第一个测试中运行代码(在单元测试框架之外)并输出键的值,它显示为["0","1"]- 我期望的.这个隐藏的第三个值在哪里,我该如何访问它?

所以,我想我最终有两个问题:

  1. 为什么另一个问题的答案对我不起作用?
  2. 第一次测试和第二次测试有什么不同?

Tik*_*vis 2

免责声明:我很确定这是正确的,但没有费心测试它。既然你已经运行了测试,你能试试我的答案吗?

查看 GitHub 上的文件,有一个名为 的帮助程序脚本koan.js。我假设它在测试之前加载,因为我懒得自己运行它们:P。(它在support目录中。)

在这个文件中,有一个名为equalTo在所有数组上定义的方法:

Array.prototype.equalTo = function(compareTo) { ... }
Run Code Online (Sandbox Code Playgroud)

所以你的问题的答案:

  1. 因为另一个问题的答案是错误的。完全被误导了。ETC。
  2. 因为该方法是在 上定义的Array而不是Object.

似乎有点平淡无奇。

如果在原型上定义这样的函数,它将被所有数组继承。尝试在控制台中定义类似的内容,然后评估[].equalTo. 然后,为了获得更多乐趣,请尝试以下操作:

for (x in []) console.log(x)
Run Code Online (Sandbox Code Playgroud)

由于此方法是在原型上定义的,因此循环也会对其进行迭代。所以测试的答案是可能0, 1, 'equalTo'。但是,如果使用 for 循环进行检查 hasOwnProperty ,它自然不会迭代该方法。

for in这确实是一个关于不使用迭代数组的实例教训:)。你永远不知道什么会潜入……巧合的是,这就是为什么prototype.js 失宠了,尽管它实际上是一个不错的框架。