假设我有一个Set
作为查找表。
const myset = new Set(["key1", "key2", "key3", "keepMe"]);
我想过滤mykeys
中其他一些键(比如myset
)的另一个数组。
const mykeys = ["ignoreMe", "keepMe", "ignoreMeToo", "key2"];
问题:
为什么我必须使用
const filtered = mykeys.filter(k => myset.has(k))
而不是
const filtered = mykeys.filter(myset.has)
// TypeError: Method Set.prototype.has called on incompatible receiver undefined
即,为什么我要在过滤器中创建匿名lambda函数? keys.has
具有相同的签名(argument - element,return boolean)。一位朋友告诉我这与this
有关。
mykeys.map(console.log)
无误地工作(尽管没有多大用处)。
我遇到了这个article at MDN,我仍然不明白为什么“'myset'没有被捕获为”。我理解变通方法而不是“为什么”。任何人都可以用人性化的方式解释一些细节和参考文献吗?
更新:谢谢大家的回复。也许我不清楚我在问什么。我确实理解变通办法。
@charlietfl明白了。这是his comment,我正在寻找的东西:
因为filter()没有隐式
this
,因为set.has
需要具有正确的this
上下文。在匿名函数内调用它并手动添加参数会使调用自包含。
答案 0 :(得分:1)
这是一个基本的设计决策,可以追溯到JavaScript语言的第一个定义。
考虑一个对象
#include <stdlib.h>
int read_int(void) {
int c;
int sign = 1;
int f = 0;
/* skip leading white space */
while ((c = fgetc(stdin)) == ' ' || c == '\n')
continue;
/* handle optional sign */
if (c == '-') {
sign = -1;
c = fgetc(stdin);
} else
if (c == '+') {
c = fgetc(stdin);
}
/* convert digits */
if (c >= '0' && c <= '9') {
f = c - '0';
while ((c = fgetc(stdin)) >= '0' && c <= '9')
f = f * 10 + c - '0';
if (c != EOF)
ungetc(c, stdin);
} else {
/* no digits: fatal error */
if (c == EOF)
printf("Unexpected end of file\n");
else
printf("Sorry that input is invalid: %c\n", c);
exit(1);
}
/* apply sign and return value */
return sign * f;
}
double read_double(void) {
char buf[80];
int c;
size_t pos = 0;
double d;
char *p;
/* read a line of input */
while (pos < sizeof(buf) - 1 && (c = fgetc(stdin)) != EOF && c != '\n')
buf[pos++] = c;
buf[pos] = '\0';
/* use standard library function to convert the number */
p = buf;
d = strtod(buf, &p);
/* if conversion failed, report fatal error */
if (p == buf) {
printf("Sorry this input is invalid: %s\n", buf);
exit(1);
}
return d;
}
现在,当你写
var myObjet = {
someValue: 0,
someFunction: function() {
return this.someValue;
}
};
你完全得到了你所添加的内容,就像你写过
一样var myValue = myObject.someValue;
同样,当你写
var myValue = 0;
你完全得到了你所添加的内容,就像你写过
一样var myFunction = myObject.someValue;
...除了现在,你不再是一个物体了。所以var myFunction = (function() {
return this.someValue;
});
并不意味着什么。的确,如果你试试
this
你会看到
console.log(myFunction());
就像你写的那样
undefined
在任何物体之外。
那么,console.log(this.someValue);
是什么?好吧,JavaScript决定如下:
this
,那么在执行myObject.myFunction()
部分时,myFunction()
为this
。myObject
,那么myFunction()
是当前的全局对象,通常为this
(并非总是如此,有许多特殊情况)。window
(例如this
,call
,apply
,...)现在,为什么要这样做?答案是这对原型来说是必要的。的确,如果你现在定义
map
您现在拥有一个基于var myDerivedObject = Object.create(myObject);
myDerivedObjet.someValue = 42;
的对象,但具有不同的属性
myObject
someValue
这是因为console.log(myObject.someFunction()); // Shows 0
console.log(myDerivedObject.someFunction()); // Shows 42
对myObject.someFunction()
使用myObject
,而this
使用myDerivedObject.someFunction()
myDerivedObject
。
如果在this
的定义过程中捕获了this
,我们就会在这两行中获得someFunction
,但这也会使原型变得不那么有用。
答案 1 :(得分:1)
您可以使用thisArg
has
的{{1}}集和thisArg
原型作为回调。
此模式不需要将Array#filter
的实例绑定到原型,因为
如果向
filter
提供this
参数,则会将其用作回调的undefined
值。否则,值this
将用作此值。callback
最终可观察到的const myset = new Set(["key1", "key2", "key3", "keepMe"]), mykeys = ["ignoreMe", "keepMe", "ignoreMeToo", "key2"], filtered = mykeys.filter(Set.prototype.has, myset); console.log(filtered);
值根据Set
确定。
$(':contains(text)')
&#13;