🐳 📖

Js coding style

📆 2020-07-12

🏷 codingjsjavascript

🖍 代码是写给人看的,顺便让计算机执行一下。

🏂 正文 👇

变量

使用有意义,可读性好的变量名
对功能类似的变量名采用统一的命名风格

1//bad
2getUserInfo()
3getClientData()
4getCustomerRecord()
5
6//good
7getUser()

不要有魔术变量,并且变量使用易于检索的名字
代码是要有解释性的

1//bad
2const cityStateRegex = /^(.+)[,\\s]+(.+?)\s*(\d{5})?$/
3saveCityState(cityStateRegex.match(cityStateRegex)[1], cityStateRegex.match(cityStateRegex)[2])
4
5//good
6const ADDRESS = 'One Infinite Loop, Cupertino 95014'
7var cityStateRegex = /^(.+)[,\\s]+(.+?)\s*(\d{5})?$/
8var match = ADDRESS.match(cityStateRegex)
9var city = match[1]
10var state = match[2]
11saveCityState(city, state)

避免重复的描述
当类/对象名已经有意义时,对其变量进行命名不需要再次重复

1//bad
2var Car = {
3 carMake: 'Honda',
4 carModel: 'Accord',
5 carColor: 'Blue',
6}
7
8function paintCar(car) {
9 car.carColor = 'Red'
10}
11
12//good
13var Car = {
14 make: 'Honda',
15 model: 'Accord',
16 color: 'Blue',
17}
18
19function paintCar(car) {
20 car.color = 'Red'
21}

利用参数默认值代替短路语法或者条件语句

1//bad
2function createMicrobrewery(name) {
3 const breweryName = name || 'Hipster Brew Co.' // ...
4}
5//good
6function createMicrobrewery(name = 'Hipster Brew Co.') {
7 // ...
8}

函数
函数参数(2 个或更少)
在需要很多参数的时候就可以使用一个对象来处理

1//bad
2function createMenu(title, body, buttonText, cancellable) {
3 // ...
4}
5
6//good
7function createMenu({ title, body, buttonText, cancellable }) {
8 // ...
9}
10
11createMenu({
12 title: 'Foo',
13 body: 'Bar',
14 buttonText: 'Baz',
15 cancellable: true,
16})

一个函数只做一件事
目前这是软件工程中最重要的原则。

1//bad
2function emailClients(clients) {
3 clients.forEach((client) => {
4 const clientRecord = database.lookup(client)
5 if (clientRecord.isActive()) {
6 email(client)
7 }
8 })
9}
10
11//good
12function emailActiveClients(clients) {
13 clients.filter(isActiveClient).forEach(email)
14}
15
16function isActiveClient(client) {
17 const clientRecord = database.lookup(client)
18 return clientRecord.isActive()
19}

函数名称要是解释性的,说明它做的事
如果你有多个层次的抽象,那么你的函数通常做了太多事情,此时应该拆分函数使其易于复用和易于测试。

1//bad
2function parseBetterJSAlternative(code) {
3 const REGEXES = [
4 // ...
5 ]
6
7 const statements = code.split(' ')
8 const tokens = []
9 REGEXES.forEach((REGEX) => {
10 statements.forEach((statement) => {
11 // ...
12 })
13 })
14
15 const ast = []
16 tokens.forEach((token) => {
17 // lex...
18 })
19
20 ast.forEach((node) => {
21 // parse...
22 })
23}
24
25//good
26function parseBetterJSAlternative(code) {
27 const tokens = tokenize(code)
28 const ast = lexer(tokens)
29 ast.forEach((node) => {
30 // parse...
31 })
32}
33
34function tokenize(code) {
35 const REGEXES = [
36 // ...
37 ]
38
39 const statements = code.split(' ')
40 const tokens = []
41 REGEXES.forEach((REGEX) => {
42 statements.forEach((statement) => {
43 tokens.push(/* ... */)
44 })
45 })
46
47 return tokens
48}
49
50function lexer(tokens) {
51 const ast = []
52 tokens.forEach((token) => {
53 ast.push(/* ... */)
54 })
55
56 return ast
57}

删除重复代码
任何情况下,都不要有重复的代码。没有任何原因,它很可能是阻碍你成为专业开发者的最糟糕的一件事。重复代码意味着你要修改某些逻辑的时候要修改不止一个地方的代码。

1//bad
2function showDeveloperList(developers) {
3 developers.forEach(developer => {
4 const expectedSalary = developer.calculateExpectedSalary()
5 const experience = developer.getExperience()
6 const githubLink = developer.getGithubLink()
7 const data = {
8 expectedSalary,
9 experience,
10 githubLink
11 }
12
13 render(data)
14 })
15}
16
17function showManagerList(managers) {
18 managers.forEach(manager => {
19 const expectedSalary = manager.calculateExpectedSalary()
20 const experience = manager.getExperience()
21 const portfolio = manager.getMBAProjects()
22 const data = {
23 expectedSalary,
24 experience,
25 portfolio
26 }
27
28 render(data)
29 })
30}
31
32//good
33function showEmployeeList(employees) {
34 employees.forEach(employee => {
35 const expectedSalary = employee.calculateExpectedSalary()
36 const experience = employee.getExperience()
37
38 const data = {
39 expectedSalary,
40 experience
41 }
42
43 switch (employee.type) {
44 case 'manager':
45 data.portfolio = employee.getMBAProjects()
46 breakcase 'developer':
47 data.githubLink = employee.getGithubLink()
48 break
49 }
50
51 render(data)
52 })
53}

用 Object.assign 设置默认对象

1//bad
2const menuConfig = {
3 title: null,
4 body: 'Bar',
5 buttonText: null,
6 cancellable: true,
7}
8
9function createMenu(config) {
10 config.title = config.title || 'Foo'
11 config.body = config.body || 'Bar'
12 config.buttonText = config.buttonText || 'Baz'
13 config.cancellable = config.cancellable !== undefined ? config.cancellable : true
14}
15
16createMenu(menuConfig)
17
18//good
19const menuConfig = {
20 title: 'Order',
21 // User did not include 'body' key
22 buttonText: 'Send',
23 cancellable: true,
24}
25
26function createMenu(config) {
27 config = Object.assign(
28 {
29 title: 'Foo',
30 body: 'Bar',
31 buttonText: 'Baz',
32 cancellable: true,
33 },
34 config
35 )
36
37 // config now equals: {title: "Order", body: "Bar", buttonText: "Send", cancellable: true}// ...
38}
39
40createMenu(menuConfig)

不要把标记用作函数参数
标记告诉你的用户这个函数做的事情不止一件。但是函数应该只做一件事。如果你的函数中会根据某个布尔参数产生不同的分支,那就拆分这个函数。

1//bad
2function createFile(name, temp) {
3 if (temp) {
4 fs.create('./temp/' + name)
5 } else {
6 fs.create(name)
7 }
8}
9
10//good
11function createTempFile(name) {
12 fs.create('./temp/' + name)
13}
14
15function createFile(name) {
16 fs.create(name)
17}

避免副作用
如果一个函数不是获取一个输入的值并返回其它值,它就有可能产生副作用。

1//bad
2// 下面的函数使用了全局变量。
3// 如果有另一个函数在使用 name,现在可能会因为 name 变成了数组而不能正常运行。
4var name = 'Ryan McDermott'
5
6function splitIntoFirstAndLastName() {
7 name = name.split(' ')
8}
9
10splitIntoFirstAndLastName()
11
12console.log(name) // ['Ryan', 'McDermott'];
13
14//good
15function splitIntoFirstAndLastName(name) {
16 return name.split(' ')
17}
18
19var name = 'Ryan McDermott'
20var newName = splitIntoFirstAndLastName(name)
21
22console.log(name) // 'Ryan McDermott';
23console.log(newName) // ['Ryan', 'McDermott'];

总是返回一个新的对象或者数组,而不是在基础上修改

1//bad
2const addItemToCart = (cart, item) => {
3 cart.push({ item, date: Date.now() })
4}
5
6//good
7const addItemToCart = (cart, item) => {
8 return [...cart, { item, date: Date.now() }]
9}

不要使用全局函数

1//bad
2Array.prototype.diff = function diff(comparisonArray) {
3 const hash = new Set(comparisonArray)
4 return this.filter((elem) => !hash.has(elem))
5}
6
7//good
8class SuperArray extends Array {
9 diff(comparisonArray) {
10 const hash = new Set(comparisonArray)
11 return this.filter((elem) => !hash.has(elem))
12 }
13}

喜欢上更好的函数式编程而不是命令式编程 封装条件

1//bad
2if (fsm.state === 'fetching' && isEmpty(listNode)) {
3 // ...
4}
5
6//good
7function shouldShowSpinner(fsm, listNode) {
8 return fsm.state === 'fetching' && isEmpty(listNode)
9}
10
11if (shouldShowSpinner(fsmInstance, listNodeInstance)) {
12 // ...
13}

避免否定条件

1//bad
2function isDOMNodeNotPresent(node) {
3 // ...
4}
5
6if (!isDOMNodeNotPresent(node)) {
7 // ...
8
9//good
10function isDOMNodePresent(node) {
11 // ...
12}
13
14if (isDOMNodePresent(node)) {
15 // ...
16}

避免条件
这似乎是个不可能完成的任务。大多数人第一次听到这个的时候会说,“没有 if 语句我该怎么办?”回答是在多数情况下都可以使用多态来实现相同的任务。第二个问题通常是,“那太好了,不过我为什么要这么做呢?”答案在于我们之前了解过整洁的概念:一个函数应该只做一件事情。如果你的类和函数有 if 语句,就意味着你的函数做了更多的事。记住,只做一件事。

1//bad
2class Airplane {
3 //...
4 getCruisingAltitude() {
5 switch (this.type) {
6 case '777':
7 return getMaxAltitude() - getPassengerCount()
8 case 'Air Force One':
9 return getMaxAltitude()
10 case 'Cessna':
11 return getMaxAltitude() - getFuelExpenditure()
12 }
13 }
14}
15
16//good
17class Airplane {
18 // ...
19}
20
21class Boeing777 extends Airplane {
22 // ...
23 getCruisingAltitude() {
24 return this.getMaxAltitude() - this.getPassengerCount()
25 }
26}
27
28class AirForceOne extends Airplane {
29 // ...
30 getCruisingAltitude() {
31 return this.getMaxAltitude()
32 }
33}
34
35class Cessna extends Airplane {
36 // ...
37 getCruisingAltitude() {
38 return this.getMaxAltitude() - this.getFuelExpenditure()
39 }
40}

使用 Array.includes 处理多重条件

1//bad
2function test(fruit) {
3 if (fruit == 'apple' || fruit == 'strawberry') {
4 console.log('red')
5 }
6}
7
8//good
9function test(fruit) {
10 // 把条件提取到数组中const redFruits = ['apple', 'strawberry', 'cherry', 'cranberries']
11
12 if (redFruits.includes(fruit)) {
13 console.log('red')
14 }
15}

少写嵌套,尽早返回 //当发现无效条件时尽早返回

1function test(fruit, quantity) {
2 const redFruits = ['apple', 'strawberry', 'cherry', 'cranberries']
3
4 // 条件 1:尽早抛出错误if (!fruit) throw new Error('No fruit!')
5
6 // 条件2:必须为红色if (redFruits.includes(fruit)) {
7 console.log('red')
8
9 // 条件 3:必须是大量存在if (quantity > 10) {
10 console.log('big quantity')
11 }
12 }
13}

相较于 switch,Map / Object 也许是更好的选择

1//根据颜色打印出各种水果
2//bad
3function test(color) {
4 // 使用 switch case 来找到对应颜色的水果switch (color) {
5 case 'red':
6 return ['apple', 'strawberry']
7 case 'yellow':
8 return ['banana', 'pineapple']
9 case 'purple':
10 return ['grape', 'plum']
11 default:
12 return []
13 }
14}
15
16//测试结果
17test(null) // []
18test('yellow') // ['banana', 'pineapple']
19
20//good
21
22//1.通过对象字面量来实现
23// 使用对象字面量来找到对应颜色的水果
24const fruitColor = {
25 red: ['apple', 'strawberry'],
26 yellow: ['banana', 'pineapple'],
27 purple: ['grape', 'plum']
28}
29
30function test(color) {
31 return fruitColor[color] || []
32}
33
34//2. 使用 Map 来找到对应颜色的水果
35const fruitColor = new Map()
36 .set('red', ['apple', 'strawberry'])
37 .set('yellow', ['banana', 'pineapple'])
38 .set('purple', ['grape', 'plum'])
39
40function test(color) {
41 return fruitColor.get(color) || []
42}
43
44//3. 使用 Array.filter 实现同样的效果
45const fruits = [
46 { name: 'apple', color: 'red' },
47 { name: 'strawberry', color: 'red' },
48 { name: 'banana', color: 'yellow' },
49 { name: 'pineapple', color: 'yellow' },
50 { name: 'grape', color: 'purple' },
51 { name: 'plum', color: 'purple' }
52]
53
54function test(color) {
55 // 使用 Array filter 来找到对应颜色的水果
56
57 return fruits.filter(f => f.color == color)
58}

使用 Array.every 和 Array.some 来处理全部/部分满足条件

1//检查是否所有的水果都是红色的
2//bad
3const fruits = [
4 { name: 'apple', color: 'red' },
5 { name: 'banana', color: 'yellow' },
6 { name: 'grape', color: 'purple' }
7]
8
9function test() {
10 let isAllRed = true
11
12 // 条件:所有的水果都必须是红色for (let f of fruits) {
13 if (!isAllRed) break
14 isAllRed = f.color == 'red'
15 }
16
17 console.log(isAllRed) // false
18}
19
20//good
21const fruits = [
22 { name: 'apple', color: 'red' },
23 { name: 'banana', color: 'yellow' },
24 { name: 'grape', color: 'purple' }
25]
26
27function test() {
28 // 条件:(简短形式)所有的水果都必须是红色const isAllRed = fruits.every(f => f.color == 'red')
29
30 console.log(isAllRed) // false
31}
32
33//想要检查是否有至少一个水果是红色的,我们可以使用 Array.some 仅用一行代码就实现出来。
34const fruits = [
35 { name: 'apple', color: 'red' },
36 { name: 'banana', color: 'yellow' },
37 { name: 'grape', color: 'purple' }
38]
39
40function test() {
41 // 条件:至少一个水果是红色的const isAnyRed = fruits.some(f => f.color == 'red')
42
43 console.log(isAnyRed) // true
44}

删除不用的代码
不用的代码和重复的代码一样糟糕。在代码库中保留无用的代码是毫无道理的事情。如果某段代码用不到,那就删掉它!如果你以后需要它,仍然可以从代码库的历史版本中找出来。

对象和数据结构


单一职责原则(SRP)
正如《代码整洁之道》所说,“不应该有超过一个原因来改变类”。往一个类里塞进许多功能是件诱人的事情,就像在坐飞机的时候只带一个手提箱一样。这带来的问题是,你的类不会在概念上有凝聚力,会有很多因素造成对它的改变。让你的类需要改变的次数最少是件非常重要的事情。这是因为如果一个类里塞入了太多功能,你只修改它的一部分,可能会让人难以理解它为何会影响代码库中其它相关模块。

1//bad
2class UserSettings {
3 constructor(user) {
4 this.user = user
5 }
6
7 changeSettings(settings) {
8 if (this.verifyCredentials(user)) {
9 // ...
10 }
11 }
12
13 verifyCredentials(user) {
14 // ...
15 }
16}
17
18//good
19class UserAuth {
20 constructor(user) {
21 this.user = user
22 }
23
24 verifyCredentials() {
25 // ...
26 }
27}
28
29class UserSettings {
30 constructor(user) {
31 this.user = user
32 this.auth = new UserAuth(user)
33 }
34
35 changeSettings(settings) {
36 if (this.auth.verifyCredentials()) {
37 // ...
38 }
39 }
40}

开放封装原则(OCP) 正如 Bertrand Meyer 所说,“软件实体(类、模块、函数等)应该对扩展开放,对修改封闭。”这是什么意思呢?这个原则基本上规定了你应该允许用户扩展你的模块,但不需要打开 .js 源代码文件来进行编辑。

1//bad
2class AjaxRequester {
3 constructor() {
4 // 如果我们需要另一个 HTTP 方法,比如 DELETE,该怎么办?// 我们必须打开这个文件然后手工把它加进去this.HTTP_METHODS = ['POST', 'PUT', 'GET']
5 }
6
7 get(url) {
8 // ...
9 }
10}
11
12//good
13class AjaxRequester {
14 constructor() {
15 this.HTTP_METHODS = ['POST', 'PUT', 'GET']
16 }
17
18 get(url) {
19 // ...
20 }
21
22 addHTTPMethod(method) {
23 this.HTTP_METHODS.push(method)
24 }
25}

多用 ES6 类语法,少用 ES5 构造函数语法 使用方法链 在类中,只需要在每个函数结束前返回 this,就实现了链式调用的类方法。

1//bad
2class Car {
3 constructor() {
4 this.make = 'Honda'this.model = 'Accord'this.color = 'white'
5 }
6
7 setMake(make) {
8 this.name = name
9 }
10
11 setModel(model) {
12 this.model = model
13 }
14
15 setColor(color) {
16 this.color = color
17 }
18
19 save() {
20 console.log(this.make, this.model, this.color)
21 }
22}
23
24let car = new Car()
25car.setColor('pink')
26car.setMake('Ford')
27car.setModel('F-150')
28car.save()
29
30//good
31class Car {
32 constructor() {
33 this.make = 'Honda'this.model = 'Accord'this.color = 'white'
34 }
35
36 setMake(make) {
37 this.name = name
38 // NOTE: 返回 this 以实现链式调用return this
39 }
40
41 setModel(model) {
42 this.model = model
43 // NOTE: 返回 this 以实现链式调用return this
44 }
45
46 setColor(color) {
47 this.color = color
48 // NOTE: 返回 this 以实现链式调用return this
49 }
50
51 save() {
52 console.log(this.make, this.model, this.color)
53 }
54}
55
56let car = new Car()
57 .setColor('pink')
58 .setMake('Ford')
59 .setModel('F-150')
60 .save()

多用组合,少用继承

1//bad
2class Employee {
3 constructor(name, email) {
4 this.name = name
5 this.email = email
6 }
7
8 // ...
9}
10
11// 这样不好,因为 Employees "拥有" 税务数据。EmployeeTaxData 不是属于 Employee 的一个类型
12class EmployeeTaxData extends Employee {
13 constructor(ssn, salary) {
14 super()
15 this.ssn = ssn
16 this.salary = salary
17 }
18
19 // ...
20}
21
22//good
23class Employee {
24 constructor(name, email) {
25 this.name = name
26 this.email = email
27 }
28
29 setTaxData(ssn, salary) {
30 this.taxData = new EmployeeTaxData(ssn, salary)
31 }
32 // ...
33}
34
35class EmployeeTaxData {
36 constructor(ssn, salary) {
37 this.ssn = ssn
38 this.salary = salary
39 }
40
41 // ...
42}

并发(Concurrency) 使用 Promise 而不是回调 async/await 比 Promise 还整洁

1//bad
2require('request-promise')
3 .get('https://en.wikipedia.org/wiki/Robert_Cecil_Martin')
4 .then(function (response) {
5 return require('fs-promise').writeFile('article.html', response)
6 })
7 .then(function () {
8 console.log('File written')
9 })
10 .catch(function (err) {
11 console.error(err)
12 })
13
14//good
15async function getCleanCodeArticle() {
16 try {
17 var request = await require('request-promise')
18 var response = await request.get('https://en.wikipedia.org/wiki/Robert_Cecil_Martin')
19 var fileHandle = await require('fs-promise')
20
21 await fileHandle.writeFile('article.html', response)
22 console.log('File written')
23 } catch (err) {
24 console.log(err)
25 }
26}

测试 测试比生产更重要。如果你不进行测试,或者测试的量不够,那你就不能肯定你写的代码不会造成破坏。测试数量依靠你的开发团队来决定,但 100% 覆盖率(所有语句和分支)能让你拥有巨大的信心,也能使程序员们安心。

每次测试一个概念

1//bad
2const assert = require('assert')
3
4describe('MakeMomentJSGreatAgain', function () {
5 it('handles date boundaries', function () {
6 let date
7
8 date = new MakeMomentJSGreatAgain('1/1/2015')
9 date.addDays(30)
10 date.shouldEqual('1/31/2015')
11
12 date = new MakeMomentJSGreatAgain('2/1/2016')
13 date.addDays(28)
14 assert.equal('02/29/2016', date)
15
16 date = new MakeMomentJSGreatAgain('2/1/2015')
17 date.addDays(28)
18 assert.equal('03/01/2015', date)
19 })
20})
21
22//good
23const assert = require('assert')
24
25describe('MakeMomentJSGreatAgain', function () {
26 it('handles 30-day months', function () {
27 let date = new MakeMomentJSGreatAgain('1/1/2015')
28 date.addDays(30)
29 date.shouldEqual('1/31/2015')
30 })
31
32 it('handles leap year', function () {
33 let date = new MakeMomentJSGreatAgain('2/1/2016')
34 date.addDays(28)
35 assert.equal('02/29/2016', date)
36 })
37
38 it('handles non-leap year', function () {
39 let date = new MakeMomentJSGreatAgain('2/1/2015')
40 date.addDays(28)
41 assert.equal('03/01/2015', date)
42 })
43})

不要把注释掉的代码留在代码库中 版本控制存在的原因就是保存你的历史代码。

避免在源文件中添加版权注释 这是代码文件树顶层的 LICENSE 文件应该干的事情。

全局常量和线程安全(在 let 和 const 之间,建议优先使用 const,尤其是在全局环境) JavaScript 编译器会对 const 进行优化,所以多使用 const,有利于提高程序的运行效率,也就是说 let 和 const 的本质区别,其实是编译器内部的处理不同。

1// bad
2var a = 1,
3 b = 2,
4 c = 3
5
6// good
7const a = 1
8const b = 2
9const c = 3
10
11// best
12const [a, b, c] = [1, 2, 3]

静态字符串一律使用单引号或反引号,不使用双引号。动态字符串使用反引号。 使用数组成员对变量赋值时,优先使用解构赋值

1const arr = [1, 2, 3, 4]
2
3// bad
4const first = arr[0]
5const second = arr[1]
6
7// good
8const [first, second] = arr

单行定义的对象,最后一个成员不以逗号结尾。多行定义的对象,最后一个成员以逗号结尾。 对象尽量静态化,一旦定义,就不得随意添加新的属性。如果添加属性不可避免,要使用 Object.assign 方法。 使用扩展运算符(…)拷贝数组 使用 Array.from 方法,将类似数组的对象转为数组 箭头函数取代 Function.prototype.bind,不应再用 self/_this/that 绑定 this。

1// bad
2const self = this
3const boundMethod = function (...params) {
4 return method.apply(self, params)
5}
6
7// acceptable
8const boundMethod = method.bind(this)
9
10// best
11const boundMethod = (...params) => method.apply(this, params)

简单的、单行的、不会复用的函数,建议采用箭头函数。如果函数体较为复杂,行数较多,还是应该采用传统的函数写法。 所有配置项都应该集中在一个对象,放在最后一个参数,布尔值不可以直接作为参数

1// bad
2function divide(a, b, option = false) {}
3
4// good
5function divide(a, b, { option = false } = {}) {}

不要在函数体内使用 arguments 变量,使用 rest 运算符(…)代替。 使用 Map,而不是 Object 注意区分 Object 和 Map,只有模拟现实世界的实体对象时,才使用 Object。如果只是需要 key: value 的数据结构,使用 Map 结构。因为 Map 有内建的遍历机制。

1let map = new Map(arr)
2
3for (let key of map.keys()) {
4 console.log(key)
5}
6
7for (let value of map.values()) {
8 console.log(value)
9}
10
11for (let item of map.entries()) {
12 console.log(item[0], item[1])
13}

总是用 Class,取代需要 prototype 的操作。 因为 Class 的写法更简洁,更易于理解。

1// bad
2function Queue(contents = []) {
3 this._queue = [...contents]
4}
5Queue.prototype.pop = function () {
6 const value = this._queue[0]
7 this._queue.splice(0, 1)
8 return value
9}
10
11// good
12class Queue {
13 constructor(contents = []) {
14 this._queue = [...contents]
15 }
16 pop() {
17 const value = this._queue[0]
18 this._queue.splice(0, 1)
19 return value
20 }
21}

使用 import 取代 require Module 语法是 JavaScript 模块的标准写法,坚持使用这种写法。

1// bad
2const moduleA = require('moduleA')
3const func1 = moduleA.func1
4const func2 = moduleA.func2
5
6// good
7import { func1, func2 } from 'moduleA'

使用 export 取代 module.exports。

1// commonJS的写法
2var React = require('react')
3
4var Breadcrumbs = React.createClass({
5 render() {
6 return <nav />
7 },
8})
9
10module.exports = Breadcrumbs
11
12// ES6的写法
13import React from 'react'
14
15class Breadcrumbs extends React.Component {
16 render() {
17 return <nav />
18 }
19}
20
21export default Breadcrumbs

如果模块只有一个输出值,就使用 export default,如果模块有多个输出值,就不使用 export default,export default 与普通的 export 不要同时使用。

如果模块默认输出一个函数,函数名的首字母应该小写。

1function makeStyleGuide() {}
2
3export default makeStyleGuide

如果模块默认输出一个对象,对象名的首字母应该大写。

1const StyleGuide = {
2 es6: {},
3}
4
5export default StyleGuide

参考资料:

👐 The End 🎉

上一篇 培养优秀品格的15条行为规范🏠下一篇十年学会编程 

👇 💬