我正在通过Wes Bos的Javascript 30。
我正在进行AJAX类型的课程,而且我试图限制我在其上做的ES6数量,仅仅是为了练习。
这是完成版本:
https://codepen.io/Airster/pen/KNYXYN
请注意,当您输入某个位置时,搜索到的值会在结果中以黄色突出显示。
现在确定这个的javascript是displayMatches函数:
var displayMatches = function(){
console.log(this.value);
var matchArray = findMatches(this.value, cities);
var html = matchArray.map(function(place){
console.log(this, place, "test");
var regex = new RegExp(this.value, 'gi');
var cityName = place.city.replace(regex, "<span class='hl'>" + this.value + "</span>");
var stateName = place.state.replace(regex, "<span class='hl'>" + this.value + "</span>");
return `
<li>
<span class="name">${cityName}, ${stateName}</span>
<span class="population">${place.population}</span>
</li>
`;
}).join("");
suggestions.innerHTML = html;
}
问题在于函数变量html
。目前我将它作为:
var html = matchArray.map(function(place){...})
这不起作用,我将在结果中得到不确定。
但是,如果我将其更改为箭头功能:
var html = matchArray.map(place => {...})
该功能将运行,搜索到的值将突出显示。
有人可以解释为什么在这个特定的环境中,箭头功能有效吗?
提前致谢!
答案 0 :(得分:4)
有人可以解释为什么在这个特定的环境中,箭头功能有效吗?
箭头函数(根据定义)保留当前词汇值#include<vector>
#include<functional>
struct B { virtual void f() = 0; };
struct D1: B { void f() override {} };
struct D2: B { void f() override {} };
void f(std::vector<std::reference_wrapper<B>> &vec) {
for(auto &w: vec) {
w.get().f();
}
}
int main() {
std::vector<std::reference_wrapper<B>> vec;
std::vector<D1> d1;
std::vector<D2> d2;
d1.push_back({});
vec.push_back(d1.back());
d2.push_back({});
vec.push_back(d2.back());
f(vec);
}
。常规回调函数没有。因此,当您使用常规回调函数时,您将失去代码所依赖的this
的正确值。
您可以通过使用保留当前范围值this
的箭头函数或通过将可选this
作为参数传递给thisArg
来解决此问题。< / p>
从.map()
的{{3}},您可以看到可选的Array.prototype.map
:
thisArg
因此,要使代码保留var new_array = arr.map(function callback(currentValue, index, array) {
// Return element for new_array
}[, thisArg])
而不使用箭头功能,您可以将this
传递给thisArg
。
.map()
仅供参考,为了完整起见,这里实际上有六种可能的解决方案:
var displayMatches = function(){
console.log(this.value);
var matchArray = findMatches(this.value, cities);
var html = matchArray.map(function(place){
console.log(this, place, "test");
var regex = new RegExp(this.value, 'gi');
var cityName = place.city.replace(regex, "<span class='hl'>" + this.value + "</span>");
var stateName = place.state.replace(regex, "<span class='hl'>" + this.value + "</span>");
return `
<li>
<span class="name">${cityName}, ${stateName}</span>
<span class="population">${place.population}</span>
</li>
`;
}, this).join(""); // <== See the this argument passed here
suggestions.innerHTML = html;
}
参数传递给this
,如上所示.map()
与回调函数.bind(this)
并引用var self = this;
而不是self
。this
,然后在回调中使用let val = this.value
(代码如下所示)。val
参数声明为事件处理程序并使用e
而不是e.target.value
,从而无需使用this.value
。由于this
具有内置.map()
的所需功能,如果您不打算使用ES6箭头功能,那么使用{{{{}}对我来说最有意义{1}}论证,但所有这四个解决方案都有效。
查看您在回调中使用this
所执行操作的详细信息,您只需阅读.map()
,这样您也可以在回调之前抓住this
在回调中也使用this.value
- 根本不需要使用let val = this.val
。
val
答案 1 :(得分:3)
问题在于,与箭头函数不同,this
变量正在为新函数进行更新。您应该将this
的值存储在一个新变量中,这样您就不会在函数中丢失它。
var displayMatches = function(){
console.log(this.value);
var that = this;
var matchArray = findMatches(this.value, cities);
var html = matchArray.map(function(place){
console.log(that, place, "test");
var regex = new RegExp(that.value, 'gi');
var cityName = place.city.replace(regex, "<span class='hl'>" + that.value + "</span>");
var stateName = place.state.replace(regex, "<span class='hl'>" + that.value + "</span>");
return `
<li>
<span class="name">${cityName}, ${stateName}</span>
<span class="population">${place.population}</span>
</li>
`;
}).join("");
suggestions.innerHTML = html;
}
答案 2 :(得分:1)
使用this
变量。当你在一个函数中使用它时,它将开始引用函数本身而不是你想要它的函数。
在使用之前将值保存到另一个变量将为您提供帮助。
const value = this.value;
const html = matchArray.map(function(place) {
const regex = new RegExp(value, 'gi');
...
});
在JavaScript中,函数是一流的对象,因为它们可以像任何其他对象一样拥有属性和方法。作为一个副作用,在函数内部使用this
变量(匿名或其他)将导致它引用自身而不是面向对象编程中常见的类对象。
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Functions#Lexical_this
箭头函数不绑定this
变量。
箭头函数不会创建自己的这个,这个值是 使用封闭执行上下文。
以下是您在codepen中的工作方式。 https://codepen.io/BoyWithSilverWings/pen/VMXyXB?editors=0010