JavaScript 箭头函数,python画箭头代码
JavaScript的arrow函数大致相当于python中的lambda函数或者Ruby中的blocks。
这些是匿名函数。它们有自己的特殊语法,接受一定数量的参数,并在其封闭范围的上下文中操作(即定义它们的函数或其他代码)。
让我们依次分解这些部分。
箭头语法
箭头整体结构单一,然后在特殊情况下可以多种方式简化。核心结构如下:
JavaScript代码:
(参数1,参数2,argumentN)={
//函数体
}
括号中是参数列表,后面是“胖箭头”(=),最后是函数体。
这和传统函数非常相似。我们只是省略了function关键字,在参数后面加了一个粗箭头(=)。
但是,有许多方法可以简化箭头函数。
首先,如果函数体是单个表达式,可以不加花括号放在内联(省略花括号,直接把表达式写成一行)。表达式的结果将由函数返回。例如:
JavaScript代码:
const add=(a,b)=a b;
其次,如果只有一个参数,甚至可以省略参数的括号。例如:
JavaScript代码:
const get first=array=array[0];
正如你所看到的,这些是一些非常简洁的语法,我们将重点关注后者的好处。
高级语法
有一些高级语法需要学习。
首先,如果您尝试使用内联单行表达式语法,但您返回的值是对象的文字量。您可能认为这应该是这样的:
JavaScript代码:
(名称,描述)={名称:名称,描述:描述};
问题是这种语法很模糊,容易造成歧义:看起来好像你在试图创建一个传统的函数体。如果您碰巧想要一个对象的单个表达式,请将该对象括在括号中:
JavaScript代码:
(名称,描述)=({名称:名称,描述:描述});
封闭上下文范围
与其他形式的函数不同,箭头函数没有自己的运行时上下文。
实际上,这意味着this和arguments都是从它们的父函数继承的。
例如,比较使用和不使用arrow函数的以下代码:
JavaScript代码:
常量测试={
名称:测试对象,
createAnonFunction: function() {
返回函数(){
console . log(this . name);
console.log(参数);
};
},
create arrow function:function(){
return ()={
console . log(this . name);
console.log(参数);
};
}
};
我们有一个简单的测试对象,它有两个方法——每个方法返回一个匿名函数。
不同的是,第一种方法使用的是传统的函数表达式,而后者使用的是箭头函数。
如果我们使用相同的参数并在控制台中运行它们,我们将得到完全不同的结果。
JavaScript代码:
const anon=test . createanonfunction( hello , world );
const arrow=test . create arrow function( hello , world );
anon();
不明确的
{}
arrow();
测试对象
{ 0 :你好, 1 :世界 }
第一个匿名函数有自己的函数上下文,因此当您调用它时,测试对象的this.name没有可用的引用,并且在创建它时没有调用任何参数。
另一方面,arrow函数与创建它的函数具有完全相同的函数上下文,因此它可以访问参数和测试对象。
使用箭头函数来改进您的代码。
传统lambda函数的一个主要用例是遍历列表中的项目,现在通过JavaScript arrow函数实现。
例如,如果您有一个值数组,并且您想使用map来遍历每个项目,那么使用arrow函数是最理想的:
JavaScript代码:
const words=[你好,世界,随便];
const downcasedWords=words . map(word=word . tolowercase());
一个非常常见的例子是从对象中提取特定值:
JavaScript代码:
const names=objects . map(object=object . name);
同样,当传统的for循环被现代的迭代风格所取代时,一般我们会使用forEach循环,而arrow函数可以将这一点瞒着父代,这使得它们非常直观。
同样,当传统的for循环被forEach取代时,arrow函数实际上会直观地将此从父级保留下来。
JavaScript代码:
this . examples . foreach(example={
this.runExample(示例);
});
承诺和承诺链
arrow另一个可以让代码更清晰直观的功能是管理异步代码。
Promises使得管理异步代码变得容易得多(即使你愉快地使用async/await,你仍然应该明白async/await是基于Promises的!)
然而,在使用promises时,您仍然需要定义在异步代码或调用完成后运行的函数。
这是箭头函数的理想位置,特别是如果您生成的函数是有状态的,并且您想要引用对象中的某个内容。例如:
JavaScript代码:
this.doSomethingAsync()。然后((结果)={
this.storeResult(结果);
});
对象转换
箭头的另一个常见且极其强大的用途是封装对象转换。
例如,在Vue.js中,有一个使用mapState将Vuex存储的各个部分直接包含到Vue组件中的通用模式。
这涉及到定义一组“映射器”,它们将从原始的完整状态对象转换为提取所涉及组件所需的内容。
对于这些简单的转换,使用arrow函数再合适不过了。例如:
JavaScript代码:
导出默认值{
计算值:{
.mapState({
结果:state=state.results
用户:state=state.users,
});
}
}
不应该使用箭头函数的场景
在许多情况下,使用箭头函数并不是一个好主意。他们不仅帮不了你,还会给你带来一些不必要的麻烦。
第一个是对象的方法。这是一个功能语境的例子,对我们理解很有帮助。
有一段时间,Class(类)属性语法和arrow函数的结合被作为创建“自动绑定方法”的一种方式。例如,事件处理程序可以使用仍然绑定到类的方法。
这看起来像这样:
JavaScript代码:
类别计数器{
计数器=0;
handleClick=()={
this.counter
}
}
这样,即使handleClick由事件处理程序调用,而不是在计数器实例的上下文中调用,它仍然可以访问实例的数据。
这种方法有许多缺点,本文对此有详细的描述。
尽管使用这种方法确实为您提供了一种绑定函数的快捷方式,但是该函数以各种非直观的方式运行。如果你试图子类化/使用这个对象作为原型,将不利于测试,同时,会造成很多问题。
相反,使用常规函数,并在必要时将其绑定到构造函数中的实例:
JavaScript代码:
类别计数器{
计数器=0;
handleClick() {
this.counter
}
构造函数(){
this . handle click=this . handle click . bind(this);
}
}
深层调用链
箭头可能给你带来麻烦的另一个地方是它们在许多不同的组合中使用,尤其是在函数的深层调用链中。
核心原因与匿名函数相同——它们给出了非常糟糕的堆栈跟踪。
如果你的函数只是下一层,比如在迭代器内部,这还不算太糟糕,但是如果你把所有的函数都定义为箭头函数,并来回调用它们,那就麻烦了,遇到错误时只会收到一条错误消息,比如:
JavaScript代码:
{匿名}()
{匿名}()
{匿名}()
{匿名}()
{匿名}()
具有动态上下文的函数
箭头可能给你带来麻烦的最后一种情况是,这是动态绑定的时候。
如果您在这些位置使用箭头函数,那么动态绑定将不起作用,您(或以后使用您的代码的其他人)可能会对为什么事情没有像预期的那样工作感到困惑。
一些典型的例子:
通过将此设置为事件的currentTarget属性来调用事件处理程序。
如果您仍在使用jQuery,大多数jQuery方法会将其设置为选定的dom元素。
如果使用的是Vue.js,方法和计算函数通常会将其设置为Vue组件。
当然,您可以故意使用arrow函数来掩盖这种行为,但尤其是在jQuery和Vue的情况下,这通常会干扰正常的操作。让你不解的是,为什么看起来和附近其他代码一样的代码却行不通。
摘要
箭头是JavaScript语言的必要补充,在很多情况下使代码更符合人们的阅读习惯。
然而,像所有其他功能一样,它们也有优点和缺点。我们应该将它们作为我们工具箱中的另一个工具,而不是作为所有功能的全面替代品。
郑重声明:本文由网友发布,不代表盛行IT的观点,版权归原作者所有,仅为传播更多信息之目的,如有侵权请联系,我们将第一时间修改或删除,多谢。