你买了一把勺子,你的邻居也买了同一个勺子。你 5 岁的孩子从抽屉里拿出你的勺子,走出家门,问一个外星人“那是爸爸的勺子吗?” - 外星人耸了耸肩。下一个场景,外星人在你家,你5岁的孩子打开抽屉,又问; “是的”外星人说。
勺子上没有你的姓名首字母。它不知道它是你的勺子。它不能也不能。好吧,直到你在上面写上你的姓名首字母,然后,它就不再是“你邻居买的同一把勺子”了。
你的函数canJoin是那个勺子,你的邻居开着幼儿园,外星人是JS运行时。
let kindergarten = {
minAge: 2,
maxAge: 6
};
function canJoin(user) {
return user.age >= this.minAge && user.age < this.maxAge;
}
army.canJoin = canJoin; kindergarten.canJoin = canJoin;
您在问题中说“canJoin 是用军队调用的” - 这是错误。
如果您选择army.canJoin({user: 9999}),那么canJoin 被称为军队 - 勺子在您的抽屉里。如果你这样做了kindergarten.canJoin({user: 9999}),那么canJoin 被叫到幼儿园——勺子在你邻居的抽屉里。如果你调用某个函数,比如Array.filter,并作为参数传递army.canJoin 或kindergarten.canJoin 或简单的canJoin,那么勺子就从抽屉里拿出来了。不可能有别的办法。在控制台中输入kindergarten.canJoin === army.canJoin。你得到true。如果你想让外星人不耸耸肩,你就是在要求不可能的事情。想想看。 不可能是其他方式 - 信息不存在。
army.canJoin=canJoin 不会修改('put initials on')canJoin 函数,kindergarten.canJoin=canJoin 也不会 - 就像将某物放入抽屉中不会在其上添加首字母一样。在institution.canJoin(...) 中,我们知道this 是institution - 函数调用发生在这里。另一方面,如果括号不存在,则不会发生函数调用。 勺子从抽屉里出来了。
正如在其他答案中指出的那样,您可以使用 bind 来“将您的姓名首字母放在勺子上”。就个人而言,我从不使用bind。我支持将整个this JS 装置(this = 'the you-know-what-I-mean-object'(除非你不知道))视为语。我更喜欢构造闭包,如下所述(以下代码将使Array.filter 在没有第二个参数的情况下工作)
function createAgeFilter(min,max){
return function(item){
return item.age>=min && item.age<max;
};
}
army.canJoin = createAgeFilter(army.minAge, army.maxAge);
kindergarten.canJoin = createAgeFilter(kindergarten.minAge, kindergarten.maxAge);
使用上述方法,可以这么说,您正在制作从一开始就带有首字母缩写的勺子,而不是稍后再使用bind。
您可能可以确认,与使用 bind 的任何内容相比,新手发现上述内容要容易得多阅读。
更新
使用 ES6 类不会 改变问题的性质。
class Army {
constructor(t){
this.tankCount=t;this.minAge=18;this.maxAge=27
}
canJoin(user){
return user.age >= this.minAge && user.age < this.maxAge;
}
}
class Kindergarten {
constructor(t){
this.toyCount=t;this.minAge=2;this.maxAge=6
}
}
Kindergarten.prototype.canJoin = Army.prototype.canJoin;
var myArmy = new Army(5);
var myKG = new Kindergarten(5);
var cast=[{name:'Susie',age:3},{name:'Agamemnon',age:5},{name:'Salome',age:18},{name:'Herod',age:40}]
function getName(u){ return u.name; }
var e1 = document.getElementById('one');
var e2 = document.getElementById('two');
var e3 = document.getElementById('three');
var e4 = document.getElementById('four');
e1.textContent = cast.filter(Army.prototype.canJoin, myArmy).map(getName).join(',');
e2.textContent = cast.filter(Army.prototype.canJoin, myKG).map(getName).join(',');
e3.textContent = cast.filter(Kindergarten.prototype.canJoin, myArmy).map(getName).join(',');
e4.textContent = cast.filter(Kindergarten.prototype.canJoin, myKG).map(getName).join(',');
<div id='one'></div>
<br>
<div id='two'></div>
<br>
<div id='three'></div>
<br>
<div id='four'></div>
Salome = {name:'Salome',age:18};
myArmy.canJoin(Salome); // true
myKG.canJoin(Solame); // false
f = myArmy.canJoin;
f(Salome); // error
注意那个错误。 f 仍然未绑定到 Army 类!仅仅因为您使用了 ES6 类,不会 使该错误消失,并且 不会(如您所见)以您可能认为的方式绑定。如果你使用这样的 ES6 类,你仍然需要第二个参数来过滤函数。