为什么airbnb风格指南表示不鼓励依赖功能名称推断?(代码片段)

author author     2023-05-13     798

关键词:

// bad
class Listing extends React.Component 
  render() 
    return <div>this.props.hello</div>;
  


// bad (relying on function name inference is discouraged)
const Listing = ( hello ) => (
  <div>hello</div>
);

// good
function Listing( hello ) 
  return <div>hello</div>;

这取自Airbnb反应风格指南。有人可以解释为什么“不鼓励依赖功能名称推断”?这只是一种风格问题吗?

答案

我认为这也可能与您可能遇到的意外行为有关,这些行为可能会隐含地将词汇名称赋予您可能期望的匿名函数。

例如,有人理解箭头功能:

(x) => x+2;

要使常规函数等效:

function(x) 
  return x+2;

期望这段代码很容易:

let foo = (x) => x+2;

那么相当于:

let foo = function(x) 
  return x+2;

函数仍然是匿名的,并且无法引用自身来执行递归等操作。

所以如果那时候,在我们幸福的无知中,我们发生了类似的事情:

let foo = (x) => (x<2) ? foo(2) : "foo(1)? I should be a reference error";
console.log(foo(1));

它会成功运行,因为该功能显然不是匿名的:

let foo = function foo(x) 
  return (x<2) ? foo(2) : "foo(1)? I should be a reference error";
  

在Babel隐式地为匿名函数添加名称的其他情况下,这可能会加剧这种情况(我认为这实际上是支持隐式函数名称的副作用,但我可能是错的在那个),他们正确处理任何边缘情况并抛出你期望的参考错误。

例如:

let foo = 
  bar: function() 
 

// Will surprisingly transpile to..

var foo = 
  bar: function bar() 
; 


// But doing something like:

var foo = 
  bar: function(x) 
    return (x<2) ? bar(2) : 'Whats happening!?';
  


console.log(foo.bar(1));

// Will correctly cause a ReferenceError: bar is not defined

你可以在这个快速的DEMO上查看'查看已编译'以查看Babel实际上是如何进行转换来维护匿名函数的行为。


简而言之,明确你正在做的事情通常是一个好主意,因为你确切地知道你的代码会有什么期望。不鼓励使用隐式函数命名可能是支持这一点的风格选择,同时也保持简洁明了。

可能还在吊装。但是,嘿,有趣的一趟。

另一答案

编辑#2:在他们的Javascript style guide找到AirBnbs的原因

不要忘记命名表达式 - 匿名函数可以使错误的调用堆栈中更难找到问题(Discussion

原答案如下

MDN对function name inference如何运作有很好的破坏,包括两个警告:

Observations

在以下两种情况下存在非标准的<function>.name推理行为:

  1. 使用脚本解释器时

仅当函数没有名为name的自己的属性时,脚本解释器才会设置函数的name属性。

  1. 使用js工具时

使用Function.name和源代码转换时要小心,例如JavaScript压缩器(缩小器)或混淆器执行的转换

....

在未压缩的版本中,程序运行到truthy-branch并且日志'foo'是'Foo'的实例,而在压缩版本中它的行为不同并且运行到else-branch。因此,如果您依赖于上面示例中的Function.name,请确保您的构建管道不会更改函数名称或不假定函数具有特定名称。

What is function name inference?

name属性返回函数的名称,或者(在ES6实现之前)为匿名函数返回一个空字符串

function doSomething() 

console.log(doSomething.name); // logs "doSomething"

使用语法new Function(...)或只是Function(...)创建的函数将其name属性设置为空字符串。在以下示例中,将创建匿名函数,因此name返回一个空字符串

var f = function() ;
var object = 
  someMethod: function() 
;

console.log(f.name == ''); // true
console.log(object.someMethod.name == ''); // also true

实现ES6函数的浏览器可以从其语法位置推断出匿名函数的名称。例如:

var f = function() ;
console.log(f.name); // "f"

Opinion

我个人更喜欢(箭头)函数分配给变量有三个基本原因:

首先,我从来没有使用过function.name

其次,将命名函数的词法范围与赋值混合感觉有点宽松:

// This...
function Blah() 
   //...

Blah.propTypes = 
 thing: PropTypes.string

// ...is the same as...
Blah.propTypes = 
 thing: PropTypes.string

function Blah() 
   //...


// ALTERNATIVELY, here lexical-order is enforced
const Blah = () => 
   //...

Blah.propTypes = 
    thing: PropTypes.string

第三,在所有条件相同的情况下,我更喜欢箭头功能:

  • 告诉读者没有this,没有arguments
  • 看起来更好(imho)
  • 性能(我上次看,箭头功能略快)

编辑:内存快照

我正在听Podcast和客人讲述他必须处理使用箭头功能和内存分析的局限性,我之前一直处于完全相同的情况。

目前,内存快照不包含变量名称 - 因此您可能会发现自己将箭头函数转换为命名函数只是为了连接内存分析器。我的经历非常简单,我对箭头功能感到满意。

另外,我只使用过一次内存快照,因此我觉得在默认情况下(主观)清晰度可以放弃一些“仪器”。

另一答案

这是因为:

const Listing = ( hello ) => (
  <div>hello</div>
);

有一个推断的列表名称,虽然它看起来像你命名它,你实际上不是:

Example

// we know the first three ways already...

let func1 = function () ;
console.log(func1.name); // func1

const func2 = function () ;
console.log(func2.name); // func2

var func3 = function () ;
console.log(func3.name); // func3

那这个呢?

const bar = function baz() 
    console.log(bar.name); // baz
    console.log(baz.name); // baz
;

function qux() 
  console.log(qux.name); // qux

另一答案

与任何其他风格指南一样,Airbnb是自以为是,并不总是很有道理。

Function name property不应该用于客户端应用程序中的任何调试,因为函数原始名称在缩小时会丢失。至于调试,如果函数在调用堆栈中没有有意义的名称,则效率会降低,因此在某些情况下保留它是有益的。

函数获取name,其功能定义如function Foo = () => 和函数名称表达式,如const Foo = () => 中的箭头。这导致Foo函数具有给定名称Foo.name === 'Foo'

一些转发器遵循规范。 Babel将此代码转换为ES5:

var Foo = function Foo() ;

TypeScript打破了规范:

var Foo = function () ;

这并不意味着命名函数表达式是坏的,应该不鼓励。只要转换器符合规范或功能名称无关紧要,就可以放弃这种担忧。

该问题适用于转换后的应用程序。它取决于使用的转换器和保持功能name属性的必要性。本机ES6中不存在此问题。

谷歌 Python 风格指南

...ythonstyleguide【发布时间】:2011-07-2213:20:53【问题描述】:为什么GooglePythonStyleGuide更喜欢列表推导和for循环而不是过滤、映射和归约?已弃用的语言功能:...“使用列表推导和for循环代替过滤、映射和归约。”给出的解释是:“... 查看详情

如何使用 Airbnb JavaScript 样式指南设置 Prettier

】如何使用AirbnbJavaScript样式指南设置Prettier【英文标题】:HowdoIsetupPrettierwithAirbnbJavaScriptStyleGuide【发布时间】:2018-01-2219:19:54【问题描述】:如何在Prettier中配置Airbnb的风格指南?我正在使用VS代码。提前致谢!【问题讨论】:... 查看详情

世界顶级互联网公司googlejavascript代码风格指南

Google和Airbnb是目前最流行的JavaScript代码风格,如果你长期使用JavaScript来写代码的话,建议对比看看。以下是我认为在Google代码风格指南中最有意思的十三条规则,和大家分享一下:使用空格,而不是tab除了行终止符外,在系统... 查看详情

依赖类型启用的编程风格的名称是啥(想想 Coq 或 Agda)?

】依赖类型启用的编程风格的名称是啥(想想Coq或Agda)?【英文标题】:Whatisthenameoftheprogrammingstyleenabledbydependenttypes(thinkCoqorAgda)?依赖类型启用的编程风格的名称是什么(想想Coq或Agda)?【发布时间】:2021-04-0303:12:01【问题描... 查看详情

vue精简版风格指南

前面的话  Vue官网的风格指南按照优先级(依次为必要、强烈推荐、推荐、谨慎使用)分类,且代码间隔较大,不易查询。本文按照类型分类,并对部分示例或解释进行缩减,是Vue风格指南的精简版 组件名称【组件名为多... 查看详情

创建名称为“flightController”的 bean 时出错:通过字段“flightrepos”表示的依赖关系不满足;

...为“flightController”的bean时出错:通过字段“flightrepos”表示的依赖关系不满足;【英文标题】:Errorcreatingbeanwithname\'flightController\':Unsatisfieddependencyexpressedthroughfield\'flightrepos\';【发布时间】:2019-02-2203:44:14【问题描述】:我在第... 查看详情

UnsatisfiedDependencyException:创建名称为“studentConrtroller”的 bean 时出错:通过字段“studentserv”表示不满足的依赖关系;

】UnsatisfiedDependencyException:创建名称为“studentConrtroller”的bean时出错:通过字段“studentserv”表示不满足的依赖关系;【英文标题】:UnsatisfiedDependencyException:Errorcreatingbeanwithname\'studentConrtroller\':Unsatisfieddependencyexpressedthroughfie 查看详情

出现错误:创建名称为“*”的 bean 时出错:通过字段“repo”表示不满足的依赖关系; n

...现错误:创建名称为“*”的bean时出错:通过字段“repo”表示不满足的依赖关系;n【英文标题】:gettingerror:Errorcreatingbeanwithname\'*\':Unsatisfieddependencyexpressedthroughfield\'repo\';n【发布时间】:2020-01-2717:09:07【问题描述】:错误:org.s... 查看详情

airbnb/javascript(代码片段)

...标准如何但求统一即可。那么本文的话,主要是基于airbnb/javascript的规范,来介绍一套规范,当然因人而异切莫对规范进行吐槽。规范来源我只选择性的挑选一些平时会忽略的规范。https://github.com/airbnb/javascriptObject大... 查看详情

为啥 jQuery 似乎不鼓励使用常规 OOP?

...OOP?【英文标题】:WhydoesjQueryseemtodiscouragetheuseofregularOOP?为什么jQuery似乎不鼓励使用常规OOP?【发布时间】:2010-11-0900:42:31【问题描述】:我们最近使用Prototype构建了一个Web应用程序,大量使用了它的Class.Create()功能。现在,我... 查看详情

不合格名称何时/为啥/如何在依赖基础中查找?

...:When/why/howdounqualifiednameslookindependentbase?不合格名称何时/为什么/如何在依赖基础中查找?【发布时间】:2021-05-3117:28:54【问题描述】:对于C++17,我在[temp.dep]p3中找到了这个措辞在类或类模板的定义中,不检查依赖基类(17.7.2.1)... 查看详情

angular2 风格指南 - 带有美元符号的属性?

】angular2风格指南-带有美元符号的属性?【英文标题】:angular2styleguide-propertywithdollarsign?【发布时间】:2016-10-0621:41:18【问题描述】:Angular.io官方指南中的Parentandchildrencommunicateviaaserviceexample在Observable流名称中使用美元符号。注... 查看详情

无法使用 eslint-config-airbnb 解析依赖关系树

】无法使用eslint-config-airbnb解析依赖关系树【英文标题】:Unabletoresolvedependencytreewitheslint-config-airbnb【发布时间】:2021-02-2815:20:53【问题描述】:当我尝试使用npxinstall-peerdeps--deveslint-config-airbnb安装eslint-config-airbnb时出现以下错误... 查看详情

markdown使用eslint和airbnb样式指南规则配置atom编辑器(代码片段)

查看详情

makefile中的特殊符号及关键字(代码片段)

1.常见自动变量和含义*:表示目标文件的名称,不包含目标文件的扩展名。+:表示所有的依赖文件,这些依赖文件之间以空格分开,按照出现的先后为顺序,其中可能包含重复的依赖文件。<:表示依赖项中第一个依赖文件的... 查看详情

为什么java不允许在函数声明中省略形式参数名称?

我想了解为什么Java设计者选择以这种方式实现函数声明。我经常听到它说Java的设计者想避免在其他语言中做出糟糕的设计选择(例如,C++)-通过类和运算符重载进行多重继承-为了保持面向对象的模型尽可能简单并鼓励良好的... 查看详情

不鼓励加班了?

...有官宣,但已经有不少字节员工证实了这一点,表示加班系统更新了工作日加班的功能,飞书里更新了一则中国内地加班规定的文档,对于加班有明确的细则。工作时间写的 查看详情

googlejava编程风格指南

前言这份文档是GoogleJava编程风格规范的完整定义。当且仅当一个Java源文件符合此文档中的规则,我们才认为它符合Google的Java编程风格。与其它的编程风格指南一样,这里所讨论的不仅仅是编码格式美不美观的问题,同时也讨论... 查看详情