【问题标题】:Array filter returns strange results数组过滤器返回奇怪的结果
【发布时间】:2016-03-26 08:20:51
【问题描述】:

与this相关的问题,我想试试这个

var arr = [0,1,2,true,4,{"abc":123},6,7,{"def":456},9,[10]];
arr.filter(Object.hasOwnProperty,"abc");//outputs [0, 1, 2]
arr.filter(Object.hasOwnProperty,"2222222") //[0, 1, 2, 4, 6]

有谁知道为什么过滤器返回这些值? Spec of filter 和 MDN doc 也没有明确说明如何使用 filter 的第二个参数。

【问题讨论】:

  • @dear-downvoters,请告诉我如何改进这个问题。
  • 规范在标题中说Array.prototype.filter ( callbackfn [ , thisArg ] ) 和“如果提供了thisArg 参数,它将用作callbackfn 的每次调用的this 值。” 在后面的段落中——还有什么比这更清楚的呢?
  • @Tomalak 好吧,我不清楚,请原谅我的无知。否则我为什么要问一个问题?说it will be used as this value for each invocation 不完全是2+2=4。
  • @Tomalak 也许您可以在链接的问题中提供见解?请照亮
  • @gurvinder372 为时已晚,但我觉得有必要添加一个答案。

标签: javascript arrays filter hasownproperty


【解决方案1】:

Array.prototype.filter 的第二个参数是将作为第一个参数传递的函数设置为 this 的值。

所以你的代码最终是这样的:

arr.filter(function(v, i, a) {
    return Object.hasOwnProperty.call("222", v, i, a);
});

所以它基本上检查"222" 字符串是否具有您在数组中枚举的属性。

从中可以清楚为什么会找到属性0、1 和2 - 因为这些是"222" 字符串中字符的索引,例如9 或{"abc":123}不是 - 因为"222" 字符串没有这样的属性。

更长的字符串也是如此,它还包括属性4和6,只是因为它更长。

一些例子:

Object.hasOwnProperty.call("222", 1); // true, because `"222"[1]` is there
Object.hasOwnProperty.call("222", 'foo'); // false, because `"222"['foo']` is not there

【讨论】:

  • 为了迂腐,不是"222"[1],而是new String("222")[1] - 自动装箱。
  • @georg "222"[1] 是一个涉及自动装箱的表达式,所以我看不出任何意义。
  • @zerkms [1,2] 在这里返回为 n var arr = [0,1,2,true,4,{"abc":123},6,7,{"def":456},9,[10]];var n = arr.filter(Object.hasOwnProperty, "abc"); 。如果将 0 替换为 7 ,则返回 [2]。为什么[1,2] 在0 在索引0 处返回,而[2] 在7 在索引0 处返回?
  • @guest271314 好的,这符合我的解释,不是吗?
  • @zerkms 您的答案提供了 “由此可以清楚为什么找到属性 0、1 和 2” ,但只返回 [1,2],而不是 0。 0 是否在 .hasOwnProperty 调用时转换为 false ?不确定为什么用7 代替0 会返回[2]?
【解决方案2】:

从规格上看很清楚

Array.prototype.filter ( callbackfn [ , thisArg ] ),

如果提供了thisArg 参数,它将用作this 值 每次调用callbackfn。

所以:

var arr = [0,1,2,true,4,{"abc":123},6,7,{"def":456},9,[10]];
arr.filter(Object.hasOwnProperty,"2222222");

依次转换为这些调用

"2222222".hasOwnProperty(0);             // true     -> 0
"2222222".hasOwnProperty(1);             // true     -> 1
"2222222".hasOwnProperty(2);             // true     -> 2
"2222222".hasOwnProperty(true);          // false    -> 
"2222222".hasOwnProperty(4);             // true     -> 4
"2222222".hasOwnProperty({"abc":123});   // false    -> 
"2222222".hasOwnProperty(6);             // true     -> 6
"2222222".hasOwnProperty(7);             // false    -> 
"2222222".hasOwnProperty({"def":456});   // false    -> 
"2222222".hasOwnProperty(9);             // false    -> 
"2222222".hasOwnProperty([10]);          // false    -> 
                                         // filter() => [0,1,2,4,6]

true 所在的行是因为字符串可以索引到类似的数组中,因此具有两个字符的字符串具有索引0 和1 作为自己的属性。

【讨论】:

  • 我们如何重新安排或以其他方式说服{"abc":123}.hasOwnProperty("abc");?虽然以正确的形式从.filter() 返回{"abc":123} ?
  • @guest271314 你的意思是({"abc":123}).hasOwnProperty("abc") ?
  • @gurvinder372 是的。安排语法正确,并让.hasOwnProperty 将{"abc":123} 识别为它正在应用属性检查的对象
  • 嗯,有人对这个和另一个答案投了反对票。这太白痴了。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-08-08
  • 2012-12-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多