Adakah fungsi anak panah tergolong dalam es6?

青灯夜游
Lepaskan: 2023-01-18 19:53:49
asal
872 orang telah melayarinya

Fungsi anak panah tergolong dalam es6. Fungsi anak panah ialah ciri baharu yang diperkenalkan dalam ES6 Gunakan anak panah "=>" untuk mentakrifkan fungsi, contohnya "var f = v => v;", yang bersamaan dengan "var f = function (v) {. return v;}; "; Jika fungsi anak panah tidak memerlukan parameter atau memerlukan berbilang parameter, gunakan kurungan untuk mewakili bahagian parameter, contohnya "var f = () =>

Adakah fungsi anak panah tergolong dalam es6?

Persekitaran pengendalian tutorial ini: sistem Windows 7, ECMAScript versi 6, komputer Dell G3.

Fungsi anak panah

Fungsi anak panah ialah ciri baharu yang diperkenalkan dalam ES6, yang menggunakan "anak panah" (=>) untuk mentakrifkan fungsi. Oleh kerana sintaks ringkas dan pengendalian kata kunci ini, fungsi anak panah telah menjadi ciri kegemaran dalam kalangan pembangun dengan cepat.

var f = v => v;
// 等同于
var f = function (v) {
  return v;
};
Salin selepas log masuk

Jika fungsi anak panah tidak memerlukan parameter atau memerlukan berbilang parameter, gunakan tanda kurung untuk mewakili bahagian parameter.

var f = () => 5;
// 等同于
var f = function () { return 5 };
var sum = (num1, num2) => num1 + num2;
// 等同于
var sum = function(num1, num2) {
  return num1 + num2;
};
Salin selepas log masuk

Jika blok kod fungsi anak panah adalah lebih daripada satu pernyataan, gunakan kurungan kerinting untuk melampirkannya dan gunakan pernyataan kembali untuk kembali.

var sum = (num1, num2) => { return num1 + num2; }
Salin selepas log masuk

Memandangkan kurungan kerinting ditafsirkan sebagai blok kod, jika fungsi anak panah mengembalikan objek secara langsung, anda mesti menambah kurungan di luar objek, jika tidak, ralat akan dilaporkan.

// 报错
let getTempItem = id => { id: id, name: "Temp" };
// 不报错
let getTempItem = id => ({ id: id, name: "Temp" });
Salin selepas log masuk

Berikut adalah kes khas, walaupun ia boleh dijalankan, ia akan mendapat hasil yang salah.

let foo = () => { a: 1 };
foo() // undefined
Salin selepas log masuk

Dalam kod di atas, niat asal adalah untuk mengembalikan objek { a: 1 }, tetapi kerana enjin berpendapat bahawa pendakap kerinting adalah blok kod, ia melaksanakan baris pernyataan a: 1 . Pada masa ini, a boleh ditafsirkan sebagai label pernyataan, jadi pernyataan yang sebenarnya dilaksanakan ialah 1;, dan kemudian fungsi itu berakhir tanpa nilai pulangan.

Jika fungsi anak panah hanya mempunyai satu baris pernyataan dan tidak perlu mengembalikan nilai, anda boleh menggunakan kaedah penulisan berikut tanpa menulis kurungan kerinting.

let fn = () => void doesNotReturn();
Salin selepas log masuk

Penjelasan:

Fungsi anak panah ialah manifestasi pengaturcaraan fungsian lebih memfokuskan pada input dan Perhubungan output menghapuskan beberapa faktor proses, jadi fungsi anak panah tidak mempunyai ini sendiri, argumen, sasaran baharu (ES6) dan super (ES6). Fungsi anak panah adalah bersamaan dengan fungsi tanpa nama, jadi baharu tidak boleh digunakan sebagai pembina.

Ini dalam fungsi anak panah sentiasa menunjuk ke ini dalam skop induknya. Dalam erti kata lain, fungsi anak panah menangkap nilai konteks ini di mana ia terletak sebagai nilai ini sendiri. Penunjuknya tidak boleh ditukar dengan sebarang kaedah, seperti call(), bind(), apply(). Apabila memanggil ini dalam fungsi anak panah, ia hanya mencari rantai skop untuk mencari ini yang terdekat dan menggunakannya Ia tiada kaitan dengan konteks panggilan. Mari jelaskan menggunakan kod.

Pulangan tersirat

Apabila hanya terdapat satu ungkapan dalam badan fungsi, anda boleh menjadikan sintaks anak panah ES6 lebih ringkas. Anda boleh meletakkan segala-galanya pada satu baris, keluarkan pendakap kerinting dan alih keluar kata kunci return.

Anda telah melihat cara satu pelapis yang bagus ini berfungsi dalam contoh di atas. Fungsi orderByLikes() berikut mengembalikan susunan objek episod Netflix, diisih mengikut bilangan suka tertinggi:

// 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)
Salin selepas log masuk

Cara penulisan ini bagus, tetapi perhatikan kebolehbacaan kod. Terutama apabila menyusun sekumpulan fungsi anak panah menggunakan sintaks anak panah ES6 baris tunggal dan tanpa kurungan. Seperti contoh ini:

const greeter = greeting => name => `${greeting}, ${name}!`
Salin selepas log masuk

Apa yang berlaku di sana? Cuba gunakan sintaks fungsi biasa:

function greeter(greeting) {
  return function(name) {
    return `${greeting}, ${name}!` 
  }
}
Salin selepas log masuk

Kini anda boleh melihat dengan cepat cara fungsi luar greeter mempunyai parameter greeting dan mengembalikan fungsi tanpa nama. Fungsi dalaman ini mengambil parameter lain yang dipanggil name dan mengembalikan rentetan menggunakan nilai greeting dan name. Begini cara untuk memanggil fungsi:

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

// output: 
"Good morning, Mary!"
Salin selepas log masuk

Perhatikan ralat pemulangan tersirat

Apabila fungsi anak panah JavaScript anda mengandungi lebih daripada satu pernyataan, anda perlu membungkusnya pendakap kerinting Balut semua pernyataan dengan kata kunci return.

Dalam kod berikut, fungsi membina objek yang mengandungi tajuk dan ringkasan beberapa episod Netflix:

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

  // explicit return
  return container
} )
Salin selepas log masuk

.map()Fungsi anak panah dalam fungsi digunakan dalam satu siri Kembangkan dalam pernyataan dan kembalikan objek pada akhir pernyataan. Ini menjadikan penggunaan pendakap di sekeliling badan fungsi tidak dapat dielakkan.

Selain itu, memandangkan pendakap kerinting sedang digunakan, pulangan tersirat bukanlah pilihan. Anda mesti menggunakan kata kunci return secara eksplisit.

Jika fungsi anda menggunakan pulangan tersirat untuk mengembalikan literal objek, anda perlu menggunakan kurungan untuk membalut literal objek. Kegagalan berbuat demikian akan mengakibatkan ralat kerana enjin JavaScript tersalah menghuraikan pendakap objek literal sebagai pendakap fungsi. Seperti yang anda baru perasan, apabila anda menggunakan pendakap kerinting dalam fungsi anak panah, anda tidak boleh meninggalkan kata kunci return.

Versi lebih pendek kod sebelumnya menunjukkan sintaks ini:

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

// Works fine
const seriesList = netflixSeries.map(series => ({ title: series.name }));
Salin selepas log masuk

Fungsi anak panah tidak boleh dinamakan

Selepas kata kunci function dan Fungsi yang tidak mempunyai pengecam nama antara senarai parameter dipanggil fungsi tanpa nama. Begini rupa ungkapan fungsi tanpa nama biasa:

const anonymous = function() {
  return 'You can\'t identify me!' 
}
Salin selepas log masuk

Fungsi anak panah adalah semua fungsi tanpa nama:

const anonymousArrowFunc = () => 'You can\'t identify me!'
Salin selepas log masuk

从ES6开始,变量和方法可以通过匿名函数的语法位置,使用name属性来推断其名称。这使得在检查函数值或报告错误时有可能识别该函数。

使用anonymousArrowFunc检查一下:

console.log(anonymousArrowFunc.name)
// output: "anonymousArrowFunc"
Salin selepas log masuk

需要注意的是,只有当匿名函数被分配给一个变量时,这个可以推断的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)
Salin selepas log masuk

这还不是全部。这个推断的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) 
})
Salin selepas log masuk

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

startBtn.addEventListener(&#39;click&#39;, function() {
  console.log(this)
  ...
})
Salin selepas log masuk

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

Adakah fungsi anak panah tergolong dalam es6?

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

startBtn.addEventListener(&#39;click&#39;, () => {
  console.log(this)
  ...
})
Salin selepas log masuk

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

Adakah fungsi anak panah tergolong dalam es6?

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

// change button&#39;s border&#39;s appearance
this.classList.add(&#39;counting&#39;)
Salin selepas log masuk

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

Adakah fungsi anak panah tergolong dalam es6?

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

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

匿名箭头函数

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

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

const timer = setInterval(function() {
  console.log(this)
  ...
}, 1000)
Salin selepas log masuk

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

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

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

const that = this
const timer = setInterval(function() {
  console.log(that)
  ...
}, 1000)
Salin selepas log masuk

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

const timer = setInterval(function() {
  console.log(this)
  ...
}.bind(this), 1000)
Salin selepas log masuk

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

const timer = setInterval( () => { 
  console.log(this)
  ...
}, 1000)
Salin selepas log masuk

Adakah fungsi anak panah tergolong dalam es6?

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

const timer = setInterval( () => { 
  console.log(this)
 // the button&#39;s text displays the timer value
  this.textContent = counter
}, 1000)
Salin selepas log masuk

箭头函数没有自己的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`
  } 
}
Salin selepas log masuk

相反,调用.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
Salin selepas log masuk

箭头函数与第三方库

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

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

$(&#39;body&#39;).on(&#39;click&#39;, function() {
  console.log(this)
})
// <body>
Salin selepas log masuk

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

$(&#39;body&#39;).on(&#39;click&#39;, () =>{
  console.log(this)
})
// Window
Salin selepas log masuk

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

new Vue({
  el: app,
  data: {
    message: &#39;Hello, World!&#39;
  },
  created: function() {
    console.log(this.message);
  }
})
// Hello, World!
Salin selepas log masuk

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
Salin selepas log masuk

箭头函数没有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;))
Salin selepas log masuk

当你调用该函数时,你会得到以下错误: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"]
Salin selepas log masuk

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

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

const listYourFavNetflixSeries = (...seriesList) => {
   return seriesList.map( (series, i) => {
     return `${series} is my #${i +1} favorite Netflix series`
   } )
 }
Salin selepas log masuk

总结

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

【相关推荐:javascript视频教程编程视频

Atas ialah kandungan terperinci Adakah fungsi anak panah tergolong dalam es6?. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

Label berkaitan:
sumber:php.cn
Kenyataan Laman Web ini
Kandungan artikel ini disumbangkan secara sukarela oleh netizen, dan hak cipta adalah milik pengarang asal. Laman web ini tidak memikul tanggungjawab undang-undang yang sepadan. Jika anda menemui sebarang kandungan yang disyaki plagiarisme atau pelanggaran, sila hubungi admin@php.cn
Tutorial Popular
Lagi>
Muat turun terkini
Lagi>
kesan web
Kod sumber laman web
Bahan laman web
Templat hujung hadapan