JavaScript 箭头函数赋值
JavaScript arrow function assignment
我尝试用谷歌搜索,但我无法与 google 讨论,有时在课程中我看到讲师将箭头函数分配给这样的变量。
const s = ( ) => { }
什么情况下我需要该语法而不使用
function s( ) { }
我的基本问题 --> 何时使用
const s = ( ) => { }
对比
function s( ) => { }
.. 为什么赋值 ...那是我的主要问题(我何时以及为什么赋值?)为什么不使用箭头函数而不将其分配给变量 ??
你的例子做了不同的事情:第一个声明了一个函数 s
,第二个调用了 s()
.
为了清楚起见...
// ES5
var multiplyES5 = function(x, y) {
return x * y;
};
// ES6
const multiplyES6 = (x, y) => {
return x * y;
};
您的示例展示了两种声明函数的方法。
这是一个 function declaration
的例子。
function s() {
// some code
}
这是定义函数的另一种方式,叫做function expression
。
const s = function() {
// some code
}
这是一个arrow function
。除了在 arrow function
和其他两个之间处理 this
的方式外,它们几乎是 3 种编写相同函数的方式。
const s = () => {
// some code
}
如以下回复所述,function declaration and function expression
是 ES5
特征,arrow function
是 ES6
特征。
箭头函数改进你的代码的地方(你应该在哪里使用它们) -
传统 lambda 函数的主要用例之一,现在是 JavaScript 中的箭头函数,用于反复应用于列表中的项目的函数。
例如,如果您有一个要使用地图转换的值数组,箭头函数是理想的选择:
const words = ['hello', 'WORLD', 'Whatever'];
const downcasedWords = words.map(word => word.toLowerCase());
一个非常常见的例子是提取一个对象的特定值:
const names = objects.map(object => object.name);
类似地,当使用 forEach 将 old-style for 循环替换为现代 iterator-style 循环时,事实是箭头函数使 this 与父函数保持一致,这使得它们非常直观。
this.examples.forEach(example => {
this.runExample(example);
});
Promises 和 Promise Chains - 箭头函数使代码更清晰、更直观的另一个地方是管理异步代码。
Promises 使管理异步代码变得更加容易(即使您很高兴使用 async/await,您仍然应该理解 async/await 构建于其之上的 promises!)
但是,虽然使用 promises 仍然需要定义在您的异步代码或调用完成后 运行 的函数。
这是放置箭头函数的理想位置,尤其是当您的结果函数是有状态的,引用对象中的某些内容时。示例:
this.doSomethingAsync().then((result) => {
this.storeResult(result);
});
对象转换 -
箭头函数的另一个常见且极其强大的用途是封装对象转换。
例如,在 Vue.js 中有一个通用模式,使用 mapState 将 Vuex 存储的片段直接包含到 Vue 组件中。
这涉及定义一组 "mappers",它将从原始的完整状态对象转换为所讨论组件所需的确切内容。
这些简单的转换是使用箭头函数的理想而美丽的地方。示例:
export default {
computed: {
...mapState({
results: state => state.results,
users: state => state.users,
});
}
}
不应该使用箭头函数的地方 -
在很多情况下箭头函数不是一个好主意。他们不仅会帮助你,还会给你带来麻烦的地方。
第一个是对象的方法。这是一个函数上下文的示例,这正是您想要的。
一段时间以来,有一种趋势是结合使用 Class 属性语法和箭头函数来创建 "auto-binding" 方法,例如事件处理程序可以使用但仍绑定到 class.
的方法
这看起来像:
class Counter {
counter = 0;
handleClick = () => {
this.counter++;
}
}
这样,即使 handleClick 是由事件处理程序而不是在 Counter 实例的上下文中调用的,它仍然可以访问实例的数据。
这种方法的缺点是多方面的,
虽然使用这种方法确实为您提供了一个 ergonomic-looking 绑定函数的捷径,但该函数的行为方式有很多不直观,如果您尝试 subclass/use 这个对象作为原型。
相反,使用常规函数并在必要时将其绑定到构造函数中的实例:
class Counter {
counter = 0;
handleClick() {
this.counter++;
}
constructor() {
this.handleClick = this.handleClick.bind(this);
}
}
深度调用链 -
箭头函数会给你带来麻烦的另一个地方是当它们被用于许多不同的组合时,特别是在函数调用的深层链中。
核心原因与匿名函数相同——它们给出的堆栈跟踪非常糟糕。
如果你的函数只向下一层,比如在迭代器内部,这还不算太糟糕,但如果你将所有函数定义为箭头函数并在它们之间来回调用,你会当您遇到错误并收到如下错误消息时会非常卡住:
{anonymous}()
{anonymous}()
{anonymous}()
{anonymous}()
{anonymous}()
具有动态上下文的函数 -
箭头函数给你带来麻烦的最后一种情况是 this 被动态绑定的地方。
如果您在这些位置使用箭头函数,动态绑定将不起作用,并且您(或稍后使用您的代码的其他人)可能会非常困惑为什么事情没有按预期工作。
这方面的一些关键示例:
- 调用事件处理程序时 this 设置为事件的 currentTarget 属性。
- 如果您仍在使用 jQuery,大多数 jQuery 方法会将 this 设置为已选择的 dom 元素。
- 如果您使用 Vue.js,方法和计算函数通常会将 this 设置为 Vue 组件。
当然你可以故意使用箭头函数来覆盖这种行为,但特别是在 jQuery 和 Vue 的情况下,这通常会干扰正常运行,让你感到困惑为什么代码看起来与其他代码相同附近不工作
这段摘录自here
我假设你在更新中指的是 function s( ) { }
。
注意该函数声明如何包含名称 s
。这 隐含地 创建一个变量 s
并将函数分配给它。箭头函数定义不包含名称。因此,在 use/call/reference 函数 elsewhere 之外,您必须将其分配给变量 显式 .
why not use the arrow function without assigning it to a variable ??
这样做的唯一原因是在定义之后加上调用括号,例如
(() => console.log('test'))()
这将立即定义并调用该函数,将 "test" 打印到控制台。
但是这样做没有多大意义,因为代码等同于只写
console.log('test')
所以在 JavaScript 中,我们一直在编写函数表达式,以至于我们决定应该使用更紧凑的语法来定义它们。这是编写函数的另一种方式。
const square = x => {
return x * x;
}
我故意在 x
周围没有括号,因为当只有一个参数时,当前语法说我们可以取消括号。
以上其实功能齐全,你可以运行square(4);
在上面得到16
.
假设您有这样的嵌套回调:
const square = function(x){
return x * x;
}
到处都是关键字 function
,过一会儿可能会让您抓狂。
箭头函数更简洁,但箭头函数不仅仅是语法糖,还有另一个区别,那就是关键字,this
。
如果您对关键字 this
没有广泛的了解,我强烈建议您开始寻找有关该主题的一些可靠信息,至少是与箭头函数相关的信息。该研究应该揭示在什么情况下您需要使用箭头函数。
至于为什么要给它赋一个变量,你得看看mph85概述的箭头函数的演变。你从函数声明开始:
function isEven(num) {
return num % 2 === 0;
}
到一个匿名函数声明,分配为一个名为 isEven
:
的变量
const isEven = function(num) {
return num % 2 === 0;
}
到分配给名为 isEven
的变量的匿名函数声明演变为分配给所述变量的箭头函数表达式。
const isEven = (num) => {
return num % 2 === 0;
}
我们可以提高赌注并使用隐式 return 使它更简洁,我们可以在其中删除括号、大括号和 return
关键字,如下所示:
const isEven = num => num % 2 === 0;
我认为观察它是如何演变的很重要,这样当你看到上面的最后一个版本时,它不会让你失望。
我尝试用谷歌搜索,但我无法与 google 讨论,有时在课程中我看到讲师将箭头函数分配给这样的变量。
const s = ( ) => { }
什么情况下我需要该语法而不使用
function s( ) { }
我的基本问题 --> 何时使用
const s = ( ) => { }
对比
function s( ) => { }
.. 为什么赋值 ...那是我的主要问题(我何时以及为什么赋值?)为什么不使用箭头函数而不将其分配给变量 ??
你的例子做了不同的事情:第一个声明了一个函数 s
,第二个调用了 s()
.
为了清楚起见...
// ES5
var multiplyES5 = function(x, y) {
return x * y;
};
// ES6
const multiplyES6 = (x, y) => {
return x * y;
};
您的示例展示了两种声明函数的方法。
这是一个 function declaration
的例子。
function s() {
// some code
}
这是定义函数的另一种方式,叫做function expression
。
const s = function() {
// some code
}
这是一个arrow function
。除了在 arrow function
和其他两个之间处理 this
的方式外,它们几乎是 3 种编写相同函数的方式。
const s = () => {
// some code
}
如以下回复所述,function declaration and function expression
是 ES5
特征,arrow function
是 ES6
特征。
箭头函数改进你的代码的地方(你应该在哪里使用它们) -
传统 lambda 函数的主要用例之一,现在是 JavaScript 中的箭头函数,用于反复应用于列表中的项目的函数。
例如,如果您有一个要使用地图转换的值数组,箭头函数是理想的选择:
const words = ['hello', 'WORLD', 'Whatever'];
const downcasedWords = words.map(word => word.toLowerCase());
一个非常常见的例子是提取一个对象的特定值:
const names = objects.map(object => object.name);
类似地,当使用 forEach 将 old-style for 循环替换为现代 iterator-style 循环时,事实是箭头函数使 this 与父函数保持一致,这使得它们非常直观。
this.examples.forEach(example => {
this.runExample(example);
});
Promises 和 Promise Chains - 箭头函数使代码更清晰、更直观的另一个地方是管理异步代码。
Promises 使管理异步代码变得更加容易(即使您很高兴使用 async/await,您仍然应该理解 async/await 构建于其之上的 promises!)
但是,虽然使用 promises 仍然需要定义在您的异步代码或调用完成后 运行 的函数。
这是放置箭头函数的理想位置,尤其是当您的结果函数是有状态的,引用对象中的某些内容时。示例:
this.doSomethingAsync().then((result) => {
this.storeResult(result);
});
对象转换 - 箭头函数的另一个常见且极其强大的用途是封装对象转换。
例如,在 Vue.js 中有一个通用模式,使用 mapState 将 Vuex 存储的片段直接包含到 Vue 组件中。
这涉及定义一组 "mappers",它将从原始的完整状态对象转换为所讨论组件所需的确切内容。
这些简单的转换是使用箭头函数的理想而美丽的地方。示例:
export default {
computed: {
...mapState({
results: state => state.results,
users: state => state.users,
});
}
}
不应该使用箭头函数的地方 -
在很多情况下箭头函数不是一个好主意。他们不仅会帮助你,还会给你带来麻烦的地方。
第一个是对象的方法。这是一个函数上下文的示例,这正是您想要的。
一段时间以来,有一种趋势是结合使用 Class 属性语法和箭头函数来创建 "auto-binding" 方法,例如事件处理程序可以使用但仍绑定到 class.
的方法这看起来像:
class Counter {
counter = 0;
handleClick = () => {
this.counter++;
}
}
这样,即使 handleClick 是由事件处理程序而不是在 Counter 实例的上下文中调用的,它仍然可以访问实例的数据。
这种方法的缺点是多方面的,
虽然使用这种方法确实为您提供了一个 ergonomic-looking 绑定函数的捷径,但该函数的行为方式有很多不直观,如果您尝试 subclass/use 这个对象作为原型。
相反,使用常规函数并在必要时将其绑定到构造函数中的实例:
class Counter {
counter = 0;
handleClick() {
this.counter++;
}
constructor() {
this.handleClick = this.handleClick.bind(this);
}
}
深度调用链 - 箭头函数会给你带来麻烦的另一个地方是当它们被用于许多不同的组合时,特别是在函数调用的深层链中。
核心原因与匿名函数相同——它们给出的堆栈跟踪非常糟糕。
如果你的函数只向下一层,比如在迭代器内部,这还不算太糟糕,但如果你将所有函数定义为箭头函数并在它们之间来回调用,你会当您遇到错误并收到如下错误消息时会非常卡住:
{anonymous}()
{anonymous}()
{anonymous}()
{anonymous}()
{anonymous}()
具有动态上下文的函数 - 箭头函数给你带来麻烦的最后一种情况是 this 被动态绑定的地方。
如果您在这些位置使用箭头函数,动态绑定将不起作用,并且您(或稍后使用您的代码的其他人)可能会非常困惑为什么事情没有按预期工作。
这方面的一些关键示例:
- 调用事件处理程序时 this 设置为事件的 currentTarget 属性。
- 如果您仍在使用 jQuery,大多数 jQuery 方法会将 this 设置为已选择的 dom 元素。
- 如果您使用 Vue.js,方法和计算函数通常会将 this 设置为 Vue 组件。
当然你可以故意使用箭头函数来覆盖这种行为,但特别是在 jQuery 和 Vue 的情况下,这通常会干扰正常运行,让你感到困惑为什么代码看起来与其他代码相同附近不工作
这段摘录自here
我假设你在更新中指的是 function s( ) { }
。
注意该函数声明如何包含名称 s
。这 隐含地 创建一个变量 s
并将函数分配给它。箭头函数定义不包含名称。因此,在 use/call/reference 函数 elsewhere 之外,您必须将其分配给变量 显式 .
why not use the arrow function without assigning it to a variable ??
这样做的唯一原因是在定义之后加上调用括号,例如
(() => console.log('test'))()
这将立即定义并调用该函数,将 "test" 打印到控制台。
但是这样做没有多大意义,因为代码等同于只写
console.log('test')
所以在 JavaScript 中,我们一直在编写函数表达式,以至于我们决定应该使用更紧凑的语法来定义它们。这是编写函数的另一种方式。
const square = x => {
return x * x;
}
我故意在 x
周围没有括号,因为当只有一个参数时,当前语法说我们可以取消括号。
以上其实功能齐全,你可以运行square(4);
在上面得到16
.
假设您有这样的嵌套回调:
const square = function(x){
return x * x;
}
到处都是关键字 function
,过一会儿可能会让您抓狂。
箭头函数更简洁,但箭头函数不仅仅是语法糖,还有另一个区别,那就是关键字,this
。
如果您对关键字 this
没有广泛的了解,我强烈建议您开始寻找有关该主题的一些可靠信息,至少是与箭头函数相关的信息。该研究应该揭示在什么情况下您需要使用箭头函数。
至于为什么要给它赋一个变量,你得看看mph85概述的箭头函数的演变。你从函数声明开始:
function isEven(num) {
return num % 2 === 0;
}
到一个匿名函数声明,分配为一个名为 isEven
:
const isEven = function(num) {
return num % 2 === 0;
}
到分配给名为 isEven
的变量的匿名函数声明演变为分配给所述变量的箭头函数表达式。
const isEven = (num) => {
return num % 2 === 0;
}
我们可以提高赌注并使用隐式 return 使它更简洁,我们可以在其中删除括号、大括号和 return
关键字,如下所示:
const isEven = num => num % 2 === 0;
我认为观察它是如何演变的很重要,这样当你看到上面的最后一个版本时,它不会让你失望。