Javascript 为什么Airbnb风格指南说不鼓励依赖函数名推断? //坏的 类列表扩展了React.Component{ render(){ 返回{this.props.hello}; } } //错误(不鼓励依赖函数名推断) 常量列表=({hello})=>( {你好} ); //好 函数列表({hello}){ 返回{hello}; }
这来自Airbnb react样式指南。有人能解释一下为什么“不鼓励依赖函数名推断”吗?这只是一个风格问题吗 这是因为:Javascript 为什么Airbnb风格指南说不鼓励依赖函数名推断? //坏的 类列表扩展了React.Component{ render(){ 返回{this.props.hello}; } } //错误(不鼓励依赖函数名推断) 常量列表=({hello})=>( {你好} ); //好 函数列表({hello}){ 返回{hello}; },javascript,reactjs,ecmascript-6,eslint,airbnb,Javascript,Reactjs,Ecmascript 6,Eslint,Airbnb,这来自Airbnb react样式指南。有人能解释一下为什么“不鼓励依赖函数名推断”吗?这只是一个风格问题吗 这是因为: // bad class Listing extends React.Component { render() { return <div>{this.props.hello}</div>; } } // bad (relying on function name inference is discouraged) const Lis
// 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>;
}
这个怎么样
// 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
}
要使正则函数等效,请执行以下操作:
(x) => x+2;
我们很容易想到以下代码:
function(x) {
return x+2;
}
相当于:
let foo = (x) => x+2;
函数保持匿名,无法引用自身来执行递归之类的操作
因此,如果在我们幸福的无知中,我们发生了这样的事情:
let foo = function(x) {
return x+2;
}
让foo=(x)=>(xEDIT#2:在其
不要忘记命名表达式-匿名函数会使在错误的调用堆栈()中查找问题变得更加困难
原始答案如下
MDN详细介绍了其工作原理,包括两个警告:
观察
在以下两种场景中存在非标准的.name
推理行为:
使用脚本解释器时
只有当函数没有自己的名为name的属性时,脚本解释器才会设置函数的name属性
使用js工具时
在使用Function.name和源代码转换(如JavaScript压缩器(minifier)或模糊器执行的转换)时要小心
在未压缩版本中,程序运行到truthy分支,日志“foo”是“foo”的一个实例,而在压缩版本中,它的行为不同,运行到else分支。因此,如果像上面的示例一样依赖Function.name,请确保生成管道不更改函数名称或不使用functti在上有一个特定的名字
什么是函数名推断?
name
属性返回函数名,或者(在ES6实现之前)返回匿名函数的空字符串
使用语法new Function(…)或just Function(…)创建的函数的name属性设置为空字符串。在以下示例中,创建了匿名函数,因此name返回空字符串
实现ES6函数的浏览器可以从匿名函数的语法位置推断其名称。例如:
var f = function() {};
var object = {
someMethod: function() {}
};
console.log(f.name == ''); // true
console.log(object.someMethod.name == ''); // also true
意见
就我个人而言,出于三个基本原因,我更喜欢(箭头)函数分配给变量:
首先,我从不使用函数。name
其次,将命名函数的词法范围与赋值混合起来感觉有点松散:
var f = function() {};
console.log(f.name); // "f"
第三,在所有条件相同的情况下,我更喜欢箭头函数:
- 与读者沟通,没有
此
,没有参数
等
- 看起来好多了(imho)
- 性能(上次我查看时,箭头函数稍微快一点)
编辑:内存快照
我正在听一位客人讲述一种情况,他必须处理使用带有内存分析的箭头函数的限制,我以前也遇到过同样的情况
目前,内存快照将不包含变量名-因此您可能会发现自己将箭头函数转换为命名函数只是为了连接内存分析器。我的经验非常简单,我仍然对箭头函数感到满意
另外,我只使用过一次内存快照,所以我觉得在默认情况下放弃一些(主观)清晰性的“工具化”是很舒服的。与任何其他风格指南一样,Airbnb是自以为是的,并不总是合理的
除了在客户端应用程序中进行调试外,不应使用,因为函数原始名称在缩小过程中丢失。至于调试,如果函数在调用堆栈中没有有意义的名称,则效率会降低,因此在某些情况下保留该名称是有益的
函数获得name
,函数定义为function Foo=()=>{}
,函数命名表达式为const Foo=()=>{}
中的箭头。这将导致Foo
函数具有给定的名称,Foo.name=='Foo'
一些Transpiler遵循规范。Babel将此代码传输到ES5:
// 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
}
TypeScript违反了规范:
var Foo = function Foo() {};
这并不意味着命名函数表达式是坏的,应该加以劝阻。只要transpiler符合规范或函数名无关紧要,就可以忽略这个问题
该问题适用于传输应用程序。这取决于正在使用的传输程序以及是否需要保留functionname
属性。本机ES6中不存在此问题。您自己的示例是否显示所有这些函数实际上都已命名?在Chrome func1中,func2和func3的name属性等于 ""我应该说得更清楚些,const bar
是要点,在那个例子中,baz
优先。@Brian:那是因为它没有实现所有ES6 Yet。我在箱子里打开了babel,Brain点击我发布的示例链接,应该没问题……函数声明通常比函数赋值更受欢迎因为它们可以提升,而且更干净/更短。@Bergi谢谢你提出“提升”这个词。我发现了一个很好的算法…或者只是看看我们的规范帖子。记住,这都是o
function doSomething() {}
console.log(doSomething.name); // logs "doSomething"
var f = function() {};
var object = {
someMethod: function() {}
};
console.log(f.name == ''); // true
console.log(object.someMethod.name == ''); // also true
var f = function() {};
console.log(f.name); // "f"
// 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
}
var Foo = function Foo() {};
var Foo = function () {};