이 기사에서는 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'
이렇게 하면 다음과 같은 이점이 있습니다.
함수
키워드 없음function
关键字return
关键字{}
在JavaScript中,函数是一等公民。你可以把函数存储在变量中,把它们作为参数传递给其他函数,并从其他函数中把它们作为值返回。你可以使用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
如果只有一个参数,你可以省略圆括号(你不必如此,但你可以这么做):
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)
在函数体内只有一个表达式时,你可以让ES6的箭头语法更加简洁。你可以把所有内容放在一行,去掉大括号,并移除return
关键字。
你已经在上面的示例中看到了这些漂亮的一行代码是如何工作的。下面的orderByLikes()
函数返回奈飞剧集对象的数组,按照最高点赞数排序:
// 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
的参数,并使用greeting
和name
的值返回一个字符串。下面是调用函数的方式:
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
关键字。
如果你的函数使用隐式返回来返回一个对象字面量,你需要使用圆括号来包裹该对象字面量。不这样做将导致错误,因为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
반환 없음) code >키워드 중괄호 없음 {}
JavaScript에서 함수는 일급 시민입니다. 함수를 변수에 저장하고, 이를 다른 함수에 인수로 전달하고, 다른 함수의 값으로 반환할 수 있습니다. JavaScript 화살표 기능을 사용하여 이러한 모든 작업을 수행할 수 있습니다.
괄호 없음 구문위 예에서 함수에는 매개변수가 없습니다. 이 경우 굵은 화살표 기호(=>
) 앞에 빈 괄호 쌍()
을 추가해야 합니다. 매개변수가 여러 개인 경우에도 마찬가지입니다.
console.log(anonymousArrowFunc.name) // output: "anonymousArrowFunc"
로그인 후 복사
로그인 후 복사
매개변수가 하나만 있는 경우 괄호를 생략할 수 있습니다(꼭 그럴 필요는 없지만 가능합니다).
let counter = 5 let countDown = setInterval(() => { console.log(counter) counter-- if (counter === 0) { console.log("I have no name!!") clearInterval(countDown) } }, 1000)
로그인 후 복사
로그인 후 복사
이 작업을 수행할 때는 주의하세요. 예를 들어, 기본 매개변수를 사용하기로 결정한 경우 매개변수를 괄호로 묶어야 합니다.
... const startBtn = document.querySelector(".start-btn"); startBtn.addEventListener('click', function() { this.classList.add('counting') let counter = 5; const timer = setInterval(() => { this.textContent = counter counter -- if(counter < 0) { this.textContent = 'THE END!' this.classList.remove('counting') clearInterval(timer) } }, 1000) })
로그인 후 복사
로그인 후 복사
Implicit return함수 본문에 표현식이 하나만 있는 경우 ES6의 화살표 구문을 더 간결하게 만들 수 있습니다. 모든 내용을 한 줄에 입력하고 중괄호를 제거하고return
키워드를 제거할 수 있습니다. 위의 예에서 이러한 멋진 한 줄짜리 코드가 어떻게 작동하는지 확인했습니다. 다음orderByLikes()
함수는 좋아요 수가 가장 많은 순서로 정렬된 Netflix 에피소드 개체 배열을 반환합니다.
startBtn.addEventListener('click', function() { console.log(this) ... })
로그인 후 복사
로그인 후 복사
이 작성 방법은 멋지지만 코드의 가독성에 주의하세요. 특히 한 줄과 괄호 없는 ES6 화살표 구문을 사용하여 여러 화살표 함수를 정렬할 때 더욱 그렇습니다. 예를 들면 다음과 같습니다.
startBtn.addEventListener('click', () => { console.log(this) ... })
로그인 후 복사
로그인 후 복사
거기서 무슨 일이 일어났나요? 일반 함수 구문을 사용해 보세요.
// change button's border's appearance this.classList.add('counting')
로그인 후 복사
로그인 후 복사
이제 외부 함수greeter
에greeting
매개변수가 있고 익명 함수를 반환하는 방법을 빠르게 확인할 수 있습니다. 이 내부 함수는name
이라는 또 다른 매개변수를 취하고greeting
및name
값을 사용하여 문자열을 반환합니다. 함수를 호출하는 방법은 다음과 같습니다.
const timer = setInterval(function() { console.log(this) ... }, 1000)
로그인 후 복사
로그인 후 복사
암시적 반환 오류에 유의하세요
JavaScript 화살표 함수에 둘 이상의 문이 포함된 경우 이를 래핑해야 합니다. 중괄호 모든 명령문을
return
키워드로 묶습니다. 아래 코드에서 이 함수는 여러 Netflix 에피소드의 제목과 요약을 포함하는 객체를 생성합니다.
const that = this const timer = setInterval(function() { console.log(that) ... }, 1000)
로그인 후 복사
로그인 후 복사
.map()
함수의 화살표 함수는 일련의 명령문에서 사용됩니다. 명령문 끝에 객체를 반환합니다. 이로 인해 함수 본문 주변에 중괄호를 사용하는 것이 불가피해졌습니다. 또한 중괄호를 사용하고 있으므로 암시적 반환은 옵션이 아닙니다.
return
키워드를 명시적으로 사용해야 합니다. 함수가 암시적 반환을 사용하여 객체 리터럴을 반환하는 경우 괄호를 사용하여 객체 리터럴을 래핑해야 합니다. 그렇게 하지 않으면 JavaScript 엔진이 객체 리터럴의 중괄호를 함수의 중괄호로 잘못 구문 분석하기 때문에 오류가 발생합니다. 방금 알아차린 것처럼 화살표 함수에 중괄호를 사용할 때는
return
키워드를 생략할 수 없습니다. 이전 코드의 더 짧은 버전은 다음 구문을 보여줍니다.
const timer = setInterval(function() { console.log(this) ... }.bind(this), 1000)
로그인 후 복사
로그인 후 복사
화살표 함수의 이름을 지정할 수 없습니다.function
키워드 및 인수 목록에서 이름으로 식별되지 않는 함수를 익명 함수라고 합니다. 일반 익명 함수 표현식은 다음과 같습니다.
const timer = setInterval( () => { console.log(this) ... }, 1000)
로그인 후 복사
로그인 후 복사
화살표 함수는 모두 익명 함수입니다.
const timer = setInterval( () => { console.log(this) // the button's text displays the timer value this.textContent = counter }, 1000)
로그인 후 복사
로그인 후 복사
ES6부터name을 사용하여 익명 함수의 구문 위치에서 변수와 메서드를 추론할 수 있습니다. code> 속성의 이름을 지정합니다. 이를 통해 해당 값을 확인하거나 오류를 보고할 때 기능을 식별할 수 있습니다. 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的反向计数器,它显示在按钮本身。
... const startBtn = document.querySelector(".start-btn"); startBtn.addEventListener('click', function() { this.classList.add('counting') let counter = 5; const timer = setInterval(() => { this.textContent = counter counter -- if(counter < 0) { this.textContent = 'THE END!' this.classList.remove('counting') clearInterval(timer) } }, 1000) })
로그인 후 복사
로그인 후 복사
注意到.addEventListener()
方法里面的事件处理器是一个常规的匿名函数表达式,而不是一个箭头函数。为什么呢?如果在函数内部打印this
的值,你会看到它引用了监听器所连接的按钮元素,这正是我们所期望的,也是程序按计划工作所需要的:
startBtn.addEventListener('click', function() { console.log(this) ... })
로그인 후 복사
로그인 후 복사
下面是它在Firefox开发人员工具控制台中的样子:
![이 기사에서는 JS 화살표 기능에 대해 설명합니다.](https://img.php.cn/upload/article/000/000/024/c468205b360a98b2c68fc9ecd91365fe-0.png)
然后,尝试使用箭头函数来替代常规函数,就像这样:
startBtn.addEventListener('click', () => { console.log(this) ... })
로그인 후 복사
로그인 후 복사
现在,this
不再引用按钮元素。相反,它引用Window
对象:
![이 기사에서는 JS 화살표 기능에 대해 설명합니다.](https://img.php.cn/upload/article/000/000/024/c468205b360a98b2c68fc9ecd91365fe-1.png)
这意味着,如果你想要在按钮被点击之后,使用this
来为按钮添加class
,你的代码就无法正常工作:
// change button's border's appearance this.classList.add('counting')
로그인 후 복사
로그인 후 복사
下面是控制台中的错误信息:
![이 기사에서는 JS 화살표 기능에 대해 설명합니다.](https://img.php.cn/upload/article/000/000/024/e5ebdf1fc20a1eb4e2c99381de9ba555-2.png)
当你在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 화살표 기능에 대해 설명합니다.](https://img.php.cn/upload/article/000/000/024/e9cd0cf4f1fd2419ffa066d86b6dcf06-3.png)
这次,控制台打印了button
,这就是我们想要的。事实上,程序要改变按钮的文本,所以它需要this
来指代button
元素:
const timer = setInterval( () => { console.log(this) // the button'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: 'After Life', 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()
方法返回'undefined has NaN likes'
,调用.addLike()
方法返回'Thank you for liking undefined, which now has NaN likes'
。因此,this.title
和this.likes
未能分别引用对象的属性title
和likes
。
这次,问题出在箭头函数的词法作用域上。对象方法中的this
引用的是父对象的范围,在本例中是Window
对象,而不是父对象本身--也就是说,不是netflixSeries
对象。
当然,解决办法是使用常规函数:
const netflixSeries = { title: 'After Life', 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元素:
$('body').on('click', function() { console.log(this) }) //
로그인 후 복사
但是如果我们使用箭头函数,正如我们所看到的,它没有自己的this
上下文,我们会得到意想不到的结果:
$('body').on('click', () =>{ console.log(this) }) // Window
로그인 후 복사
下面是使用Vue的其他例子:
new Vue({ el: app, data: { message: 'Hello, World!' }, created: function() { console.log(this.message); } }) // Hello, World!
로그인 후 복사
在created
钩子内部,this
被绑定到Vue实例上,因此会显示'Hello, World!'
信息。
然而如果我们使用箭头函数,this
将会指向父作用域,上面没有message
属性:
new Vue({ el: app, data: { message: 'Hello, World!' }, 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('Bridgerton', 'Ozark', 'After Life'))
로그인 후 복사
当你调用该函数时,你会得到以下错误: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('Bridgerton', 'Ozark', 'After Life')) // 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函数。记住,只有当箭形函数是正确的工具时,才能使用它。
以上就是本文的所有内容,如果对你有所帮助,欢迎点赞收藏转发~
【推荐学习:javascript视频教程】
위 내용은 이 기사에서는 JS 화살표 기능에 대해 설명합니다.의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!