当前位置: 首页 > 知识库问答 >
问题:

为什么Airbnb风格指南说不鼓励依赖函数名推断?

朱英范
2023-03-14
// 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 react样式指南。有人能解释一下为什么“不鼓励依赖函数名推断”吗?这只是一个风格问题吗?

共有3个答案

左丘曦
2023-03-14

这是因为:

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

有一个推断的列表名称,虽然看起来您正在命名它,但实际上您没有:

实例

// 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
}
慎建本
2023-03-14

不要忘记命名表达式-匿名函数会使在错误的调用堆栈中查找问题变得更加困难(讨论)

MDN对函数名推理的工作原理有一个很好的总结,包括两个警告:

存在非标准

  1. 使用脚本解释器时

脚本解释器将设置一个函数的name属性只有当一个函数没有自己的属性称为name...

在使用Function.name和源代码转换(如JavaScript压缩器(minifier)或模糊器执行的转换)时要小心

....

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

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

function doSomething() {}

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

使用语法new Function(…)或just 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"

就我个人而言,出于三个基本原因,我更喜欢(箭头)函数分配给变量:

首先,我从不使用函数。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,没有参数etc
  • 看起来好多了(imho)
  • 性能(上次我查看时,箭头函数略快)

我在听一个播客,嘉宾告诉我一个情况,如果他不得不处理在内存分析中使用箭头函数的局限性,我以前也遇到过同样的情况。

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

另外,我只使用过一次内存快照,所以默认情况下,为了(主观的)清晰性,我觉得放弃一些“工具”是很舒服的。

公羊英达
2023-03-14

我认为这也可能与您可能遇到的意外行为有关,从隐式地给一个词法名称到您可能期望的匿名函数。

例如,假设某人理解箭头功能:

(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

您可以在这个快速演示中检查“视图编译”,看看巴别塔实际上是如何转置它来维持匿名函数的行为的。

简言之,明确您正在做的事情通常是一个好主意,因为您确切地知道从代码中期望得到什么。不鼓励使用隐式函数命名可能是支持这一点的一种文体选择,同时也要保持简洁明了。

可能是起重。但是,嘿,有趣的边旅行。

 类似资料:
  • 问题内容: 这取自Airbnb react样式指南。有人可以解释为什么“不鼓励依赖函数名推断”吗?只是样式问题吗? 问题答案: 我认为这也可能与您可能会遇到的意外行为有关,从隐式地将词法名称赋予您可能希望使用的匿名函数可能会遇到这种意外行为。 例如说有人理解了箭头功能: 要使常规功能等效: 期望这段代码非常容易: 然后等于: 该函数仍然是匿名的,无法引用自身来执行诸如递归的操作。 因此,如果那时,

  • 这是 Airbnb 的 Ruby 代码风格指南,指南灵感来自于 Github 的指南 和 Bozhidar Batsov 的指南,Airbnb 也在维护 JavaScript 风格指南。

  • 大多数在线来源都表明您可以静态链接glibc,但不鼓励这样做;例如centos包repo: glibc静态包包含用于静态链接的C库静态库。你不需要这些,除非你静态链接,这是非常不鼓励的。 这些消息来源很少(或从未)说明为什么这是个坏主意。

  • 最近,我开始查看各种JavaScript样式指南,我最喜欢Airbnb。 然而,当我用Airbnb样式指南配置ESLint时,我注意到他们文档中定义的一些规则根本没有被检查。例如: 将所有,然后将所有分组 所以,如果你以这段代码为例: 过梁应抛出3个错误: 我没有将所有consts和let分组,我按顺序定义了它们。 我没有在if语句中使用显式比较-

  • 介绍 在参与 Vant 开发时,请遵守约定的单文件组件风格指南,指南内容节选自 Vue 官方风格指南。 组件数据 组件的 data 必须是一个函数。 // bad export default { data: { foo: 'bar', }, }; // good export default { data() { return { foo: 'bar',

  • 这是CatLib特有的代码风格指南,如果您在您的项目中使用CatLib,为了避免错误,降低沟通成本,小纠结和 反模式,阅读本指南是一份不错的选择。 我们不能保证风格指南中的所有内容,对于所有工程和团队都是理想的,所以根据项目环境,周围技术环境,风格出现偏差是可行的。 我们应该尽可能的遵守本风格指南提出的建议。 根据周围技术堆栈对于命名规范相关我们建议您阅读微软提供的:框架设计指南 优先级定义 (A