将箭头函数转换为常规函数?

时间:2017-10-09 05:18:09

标签: javascript ecmascript-6

我正在通过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 => {...})

该功能将运行,搜索到的值将突出显示。

有人可以解释为什么在这个特定的环境中,箭头功能有效吗?

提前致谢!

3 个答案:

答案 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()

仅供参考,为了完整起见,这里实际上有六种可能的解决方案:

  1. 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,如上所示
  2. 使用箭头功能(仅限ES6)
  3. .map()与回调函数
  4. 一起使用
  5. 创建本地变量.bind(this)并引用var self = this;而不是self
  6. 在回调之前使用this,然后在回调中使用let val = this.value(代码如下所示)。
  7. val参数声明为事件处理程序并使用e而不是e.target.value,从而无需使用this.value
  8. 由于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