この記事では、JS のアロー関数について説明します。

青灯夜游
リリース: 2022-11-10 16:08:56
転載
1755 人が閲覧しました

この記事では、JS のアロー関数について説明します。

この記事では、JavaScript のアロー関数についてすべて説明します。 ES6 のアロー構文の使用方法と、コード内でアロー関数を使用するときに注意すべきよくある間違いをいくつか紹介します。それらがどのように機能するかを示す例がたくさんあります。

JavaScript のアロー関数は、ES6 としても知られる ECMAScript 2015 のリリースとともに導入されました。アロー関数は、その簡潔な構文と this キーワードの処理により、すぐに開発者の間で人気の機能になりました。

アロー関数の構文

関数は、アクションの実行や戻り値など、プログラム内で実行する必要があることを達成するための有用な命令を保存するレシピのようなものです。価値。関数を呼び出すことにより、レシピに含まれるステップを実行します。レシピを何度も書き直すことなく、関数を呼び出すたびにこれを行うことができます。

関数を宣言して JavaScript で呼び出す標準的な方法は次のとおりです:

// function declaration
function sayHiStranger() {
  return 'Hi, stranger!'
}

// call the function
sayHiStranger()
ログイン後にコピー

次のように、同じ関数を関数式として記述することもできます:

const sayHiStranger = function () {
  return 'Hi, stranger!'
}
ログイン後にコピー

JavaScript アロー関数は常に式です。矢印表記を使用して上記の関数を書き直す方法は次のとおりです:

const sayHiStranger = () => 'Hi, stranger'
ログイン後にコピー

これを行う利点は次のとおりです:

  • コードは 1 行のみです
  • Nofunction キーワード
  • Noreturnキーワード
  • 中かっこなし{}

JavaScriptでは、関数Aが最初です-階級市民。関数を変数に保存し、他の関数に引数として渡し、他の関数から値として返すことができます。 JavaScript アロー関数を使用すると、これらすべてを行うことができます。

括弧なしの構文

上記の例では、関数にはパラメーターがありません。この場合、太い矢印記号 (=>) の前に空のかっこ () を追加する必要があります。複数のパラメータがある場合も同様です:

const getNetflixSeries = (seriesName, releaseDate) => `The ${seriesName} series was released in ${releaseDate}`
// call the function
console.log(getNetflixSeries('Bridgerton', '2020') )
// output: The Bridgerton series was released in 2020
ログイン後にコピー

パラメータが 1 つだけの場合は、括弧を省略できます (必須ではありませんが、省略できます):

const favoriteSeries = seriesName => seriesName === "Bridgerton" ? "Let's watch it" : "Let's go out"
// call the function
console.log(favoriteSeries("Bridgerton"))
// output: "Let's watch it"
ログイン後にコピー

常に注意してください。たとえば、デフォルトのパラメータを使用する場合は、パラメータをかっこで囲む必要があります。

// with parentheses: correct
const bestNetflixSeries = (seriesName = "Bridgerton") => `${seriesName} is the best`
// outputs: "Bridgerton is the best"
console.log(bestNetflixSeries())

// no parentheses: error
const bestNetflixSeries = seriesName = "Bridgerton" => `${seriesName} is the best`
// Uncaught SyntaxError: invalid arrow-function arguments (parentheses around the arrow-function may help)
ログイン後にコピー

Implicit return

関数本体に式が 1 つだけある場合、 ES6 の矢印構文をより簡潔にすることができます。すべてを 1 行に入力し、中かっこを削除し、return キーワードを削除します。

上記の例で、これらの気の利いたワンライナーがどのように機能するかを見てきました。次の orderByLikes() 関数は、いいね数の多い順に並べ替えられた Netflix エピソード オブジェクトの配列を返します。

// using the JS sort() function to sort the titles in descending order 
// according to the number of likes (more likes at the top, fewer at the bottom
const orderByLikes = netflixSeries.sort((a, b) => b.likes - a.likes)

// call the function 
// output:the titles and the n. of likes in descending order
console.log(orderByLikes)
ログイン後にコピー

この書き方は素晴らしいですが、読みやすさに注意してください。コード。特に、単一行で括弧のない ES6 矢印構文を使用して、多数の矢印関数を並べ替える場合に便利です。次の例のように:

const greeter = greeting => name => `${greeting}, ${name}!`
ログイン後にコピー

そこで何が起こったのですか?通常の関数構文を使用してみます。

function greeter(greeting) {
  return function(name) {
    return `${greeting}, ${name}!` 
  }
}
ログイン後にコピー

これで、外部関数 greeter がパラメータ greeting を持ち、匿名関数を返す様子がすぐにわかります。この内部関数は、name という別のパラメータを受け取り、greetingname の値を使用して文字列を返します。関数を呼び出す方法は次のとおりです。

const myGreet = greeter('Good morning')
console.log( myGreet('Mary') )   

// output: 
"Good morning, Mary!"
ログイン後にコピー

暗黙的な戻りエラーに注意してください

JavaScript アロー関数に複数のステートメントが含まれている場合は、それらをすべてカーリーで囲む必要があります。中括弧ステートメントを使用し、return キーワードを使用します。

次のコードでは、関数は、いくつかの Netflix エピソードのタイトルと概要を含むオブジェクトを作成します。関数内の

const seriesList = netflixSeries.map( series => {
  const container = {}
  container.title = series.name 
  container.summary = series.summary

  // explicit return
  return container
} )
ログイン後にコピー

.map() アロー関数は、次のように展開されます。一連のステートメント。ステートメントの最後にオブジェクトを返します。このため、関数本体の周囲に中括弧を使用することが避けられなくなります。

また、中括弧が使用されているため、暗黙的な return はオプションではありません。 return キーワードを明示的に使用する必要があります。

関数が暗黙的な return を使用してオブジェクト リテラルを返す場合、かっこを使用してオブジェクト リテラルをラップする必要があります。これを行わないと、JavaScript エンジンがオブジェクト リテラルの中括弧を関数の中括弧として誤って解析するため、エラーが発生します。お気づきのとおり、アロー関数で中かっこを使用する場合は、return キーワードを省略できません。

上記のコードの短いバージョンは、次の構文を示しています。

// Uncaught SyntaxError: unexpected token: ':'
const seriesList = netflixSeries.map(series => { title: series.name });

// Works fine
const seriesList = netflixSeries.map(series => ({ title: series.name }));
ログイン後にコピー

function

キー関数でアロー関数

に名前を付けることはできません。単語とパラメータリストの間に名前識別子がないものは、匿名関数と呼ばれます。通常の匿名関数式は次のようになります:

const anonymous = function() {
  return 'You can\'t identify me!' 
}
ログイン後にコピー

アロー関数はすべて匿名関数です:

const anonymousArrowFunc = () => 'You can\'t identify me!'
ログイン後にコピー

ES6 以降、変数とメソッドは匿名関数の構文位置を介して渡すことができます。 name 属性を使用して名前を推測します。これにより、値を確認したりエラーを報告したりするときに関数を識別できるようになります。

anonymousArrowFunc を使用してください:

console.log(anonymousArrowFunc.name)
// output: "anonymousArrowFunc"
ログイン後にコピー

需要注意的是,只有当匿名函数被分配给一个变量时,这个可以推断的name属性才会存在,正如上面的例子。如果你使用匿名函数作为回调函数,你就会失去这个有用的功能。在下面的演示中,.setInterval()方法中的匿名函数无法利用name属性:

let counter = 5
let countDown = setInterval(() => {
  console.log(counter)
  counter--
  if (counter === 0) {
    console.log("I have no name!!")
    clearInterval(countDown)
  }
}, 1000)
ログイン後にコピー

这还不是全部。这个推断的name属性仍然不能作为一个适当的标识符,你可以用它来指代函数本身--比如递归、解除绑定事件等。

如何处理this关键字

关于箭头函数,最重要的一点是它们处理this关键字的方式。特别是,箭头函数内的this关键字不会重新绑定。

为了说明这意味着什么,请查看下面的演示。

这里有一个按钮。点击按钮会触发一个从5到1的反向计数器,它显示在按钮本身。

<button class="start-btn">Start Counter</button>

...

const startBtn = document.querySelector(".start-btn");

startBtn.addEventListener(&#39;click&#39;, function() {
  this.classList.add(&#39;counting&#39;)
  let counter = 5;
  const timer = setInterval(() => {
    this.textContent = counter 
    counter -- 
    if(counter < 0) {
      this.textContent = &#39;THE END!&#39;
      this.classList.remove(&#39;counting&#39;)
      clearInterval(timer)
    }
  }, 1000) 
})
ログイン後にコピー

注意到.addEventListener()方法里面的事件处理器是一个常规的匿名函数表达式,而不是一个箭头函数。为什么呢?如果在函数内部打印this的值,你会看到它引用了监听器所连接的按钮元素,这正是我们所期望的,也是程序按计划工作所需要的:

startBtn.addEventListener(&#39;click&#39;, function() {
  console.log(this)
  ...
})
ログイン後にコピー

下面是它在Firefox开发人员工具控制台中的样子:

この記事では、JS のアロー関数について説明します。

然后,尝试使用箭头函数来替代常规函数,就像这样:

startBtn.addEventListener(&#39;click&#39;, () => {
  console.log(this)
  ...
})
ログイン後にコピー

现在,this不再引用按钮元素。相反,它引用Window对象:

この記事では、JS のアロー関数について説明します。

这意味着,如果你想要在按钮被点击之后,使用this来为按钮添加class,你的代码就无法正常工作:

// change button&#39;s border&#39;s appearance
this.classList.add(&#39;counting&#39;)
ログイン後にコピー

下面是控制台中的错误信息:

この記事では、JS のアロー関数について説明します。

当你在JavaScript中使用箭头函数,this关键字的值不会被重新绑定。它继承自父作用域(也称为词法作用域)。在这种特殊情况下,箭头函数被作为参数传递给startBtn.addEventListener()方法,该方法位于全局作用域中。因此,函数处理器中的this也被绑定到全局作用域中--也就是Window对象。

因此,如果你想让this引用程序中的开始按钮,正确的做法是使用一个常规函数,而不是一个箭头函数。

匿名箭头函数

在上面的演示中,接下来要注意的是.setInterval()方法中的代码。在这里,你也会发现一个匿名函数,但这次是一个箭头函数。为什么?

请注意,如果你使用常规函数,this值会是多少:

const timer = setInterval(function() {
  console.log(this)
  ...
}, 1000)
ログイン後にコピー

button元素吗?并不是。这个值将会是Window对象!

事实上,上下文已经发生了变化,因为现在this在一个非绑定的或全局的函数中,它被作为参数传递给.setInterval() 。因此,this关键字的值也发生了变化,因为它现在被绑定到全局作用域。

在这种情况下,一个常见的hack手段是包括另一个变量来存储this关键字的值,这样它就会一直指向预期的元素--在这种情况下,就是button元素:

const that = this
const timer = setInterval(function() {
  console.log(that)
  ...
}, 1000)
ログイン後にコピー

你也可以使用.bind()来解决这个问题:

const timer = setInterval(function() {
  console.log(this)
  ...
}.bind(this), 1000)
ログイン後にコピー

有了箭头函数,问题就彻底消失了。下面是使用箭头函数时this的值:

const timer = setInterval( () => { 
  console.log(this)
  ...
}, 1000)
ログイン後にコピー

この記事では、JS のアロー関数について説明します。

这次,控制台打印了button,这就是我们想要的。事实上,程序要改变按钮的文本,所以它需要this来指代button元素:

const timer = setInterval( () => { 
  console.log(this)
 // the button&#39;s text displays the timer value
  this.textContent = counter
}, 1000)
ログイン後にコピー

箭头函数没有自己的this上下文。它们从父级继承this的值,正是因为这个特点,在上面这种情况下就是很好的选择。

不正常工作的情况

箭头函数并不只是在JavaScript中编写函数的一种花里胡哨的新方法。它们有自己的局限性,这意味着在有些情况下你不想使用箭头函数。让我们看看更多的例子。

箭头函数作为对象方法

箭头函数作为对象上的方法不能很好地工作。

考虑这个netflixSeries对象,上面有一些属性和一系列方法。调用console.log(netflixSeries.getLikes()) 应该会打印一条信息,说明当前喜欢的人数。console.log(netflixSeries.addLike())应该会增加一个喜欢的人数,然后在控制台上打印新值:

const netflixSeries = {
  title: &#39;After Life&#39;, 
  firstRealease: 2019,
  likes: 5,
  getLikes: () => `${this.title} has ${this.likes} likes`,
  addLike: () => {  
    this.likes++
    return `Thank you for liking ${this.title}, which now has ${this.likes} likes`
  } 
}
ログイン後にコピー

相反,调用.getLikes()方法返回&#39;undefined has NaN likes&#39;,调用.addLike()方法返回&#39;Thank you for liking undefined, which now has NaN likes&#39;。因此,this.titlethis.likes未能分别引用对象的属性titlelikes

这次,问题出在箭头函数的词法作用域上。对象方法中的this引用的是父对象的范围,在本例中是Window对象,而不是父对象本身--也就是说,不是netflixSeries对象。

当然,解决办法是使用常规函数:

const netflixSeries = {
  title: &#39;After Life&#39;, 
  firstRealease: 2019,
  likes: 5,
  getLikes() {
    return `${this.title} has ${this.likes} likes`
  },
  addLike() { 
    this.likes++
    return `Thank you for liking ${this.title}, which now has ${this.likes} likes`
  } 
}

// call the methods 
console.log(netflixSeries.getLikes())
console.log(netflixSeries.addLike())

// output: 
After Life has 5 likes
Thank you for liking After Life, which now has 6 likes
ログイン後にコピー

箭头函数与第三方库

另一个需要注意的问题是,第三方库通常会绑定方法调用,因此this值会指向一些有用的东西。

比如说,在Jquery事件处理器内部,this将使你能够访问处理器所绑定的DOM元素:

$(&#39;body&#39;).on(&#39;click&#39;, function() {
  console.log(this)
})
// <body>
ログイン後にコピー

但是如果我们使用箭头函数,正如我们所看到的,它没有自己的this上下文,我们会得到意想不到的结果:

$(&#39;body&#39;).on(&#39;click&#39;, () =>{
  console.log(this)
})
// Window
ログイン後にコピー

下面是使用Vue的其他例子:

new Vue({
  el: app,
  data: {
    message: &#39;Hello, World!&#39;
  },
  created: function() {
    console.log(this.message);
  }
})
// Hello, World!
ログイン後にコピー

created钩子内部,this被绑定到Vue实例上,因此会显示&#39;Hello, World!&#39;信息。

然而如果我们使用箭头函数,this将会指向父作用域,上面没有message属性:

new Vue({
  el: app,
  data: {
    message: &#39;Hello, World!&#39;
  },
  created: () => {
    console.log(this.message);
  }
})
// undefined
ログイン後にコピー

箭头函数没有arguments对象

有时,你可能需要创建一个具有无限参数个数的函数。比如,假设你想创建一个函数,列出你最喜欢的奈飞剧集,并按照偏好排序。然而,你还不知道你要包括多少个剧集。JavaScript提供了arguments对象。这是一个类数组对象(不是完整的数组),在调用时存储传递给函数的值。

尝试使用箭头函数实现此功能:

const listYourFavNetflixSeries = () => {
  // we need to turn the arguments into a real array 
  // so we can use .map()
  const favSeries = Array.from(arguments) 
  return favSeries.map( (series, i) => {
    return `${series} is my #${i +1} favorite Netflix series`  
  } )
  console.log(arguments)
}

console.log(listYourFavNetflixSeries(&#39;Bridgerton&#39;, &#39;Ozark&#39;, &#39;After Life&#39;))
ログイン後にコピー

当你调用该函数时,你会得到以下错误:Uncaught ReferenceError: arguments is not defined。这意味着arguments对象在箭头函数中是不可用的。事实上,将箭头函数替换成常规函数就可以了:

const listYourFavNetflixSeries = function() {
   const favSeries = Array.from(arguments) 
   return favSeries.map( (series, i) => {
     return `${series} is my #${i +1} favorite Netflix series`  
   } )
   console.log(arguments)
 }
console.log(listYourFavNetflixSeries(&#39;Bridgerton&#39;, &#39;Ozark&#39;, &#39;After Life&#39;))

// output: 
["Bridgerton is my #1 favorite Netflix series",  "Ozark is my #2 favorite Netflix series",  "After Life is my #3 favorite Netflix series"]
ログイン後にコピー

因此,如果你需要arguments对象,你不能使用箭头函数。

但如果你真的想用一个箭头函数来复制同样的功能呢?你可以使用ES6剩余参数(...)。下面是你该如何重写你的函数:

const listYourFavNetflixSeries = (...seriesList) => {
   return seriesList.map( (series, i) => {
     return `${series} is my #${i +1} favorite Netflix series`
   } )
 }
ログイン後にコピー

总结

通过使用箭头函数,你可以编写带有隐式返回的单行代码,以解决JavaScript中this关键字的绑定问题。箭头函数在数组方法中也很好用,如.map().sort().forEach().filter()、和.reduce()。但请记住:箭头函数并不能取代常规的JavaScript函数。记住,只有当箭形函数是正确的工具时,才能使用它。

以上就是本文的所有内容,如果对你有所帮助,欢迎点赞收藏转发~

原文链接:www.sitepoint.com/arrow-funct…

作者:Maria Antonietta Perna

【推荐学习:javascript视频教程

以上がこの記事では、JS のアロー関数について説明します。の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

関連ラベル:
ソース:juejin.cn
このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
最新の問題
人気のチュートリアル
詳細>
最新のダウンロード
詳細>
ウェブエフェクト
公式サイト
サイト素材
フロントエンドテンプレート