必备!前端开发的代码规范指南
在日常工作中,我们要想代码写的质量高,写的漂亮,那一定需要一套代码规范,以下代码规范是来自 京东凹凸实验室 ,在此也是想留作笔记以作日常复习。
CSS代码规范
代码风格
样式书写有两种风格,一种是紧凑型(Compact)
.jdc{ dispaly: block; width: 50px;}
一种是展开型(Expanded)
.jdc {
dispaly: block;
width: 50px;
}
团队中统一约定展开格式书写
代码大小写
样式选择器,属性名,属性值关键字全部使用小写字母书写,属性字符串允许使用大小写。
/* 推荐 */
.jdc {
display: block;
}
/* 不推荐 */
.JDC {
DISPLAY: BLOCK;
}
选择器
尽量少用通用选择器 * 不使用 ID 选择器 不使用无具体语义定义的标签选择器
/* 推荐 */
.jdc {}
.jdc li {}
.jdc li p {}
/* 不推荐 */
*{}
#jdc {}
.jdc div{}
代码缩进
统一使用四个空格进行代码缩进,使得各编辑器表现一致(各编辑器有相关配置)
.jdc {
width: 100%;
height: 100%;
}
分号
每个属性声明末尾都要加分号;
.jdc {
width: 100%;
height: 100%;
}
代码易读性
左括号与类名之间一个空格,冒号与属性之间一个空格
推荐:
.jdc {
width: 100%;
}
不推荐:
.jdc{
width:100%;
}
逗号分隔的取值,逗号之后一个空格
推荐:
.jdc {
box-shadow: 1px 1px 1px #333, 2px 2px 2px #ccc;
}
不推荐:
.jdc {
box-shadow: 1px 1px 1px #333,2px 2px 2px #ccc;
}
为单个css选择器或新申明开启新行
推荐:
.jdc,
.jdc_logo,
.jdc_hd {
color: #ff0;
}
.nav {
color: #fff;
}
不推荐:
.jdc,.jdc,.jdc_hd{
color: #ff0;
}.nav{
color: #fff;
}
颜色值 rgb() rgba() hsl() hsla() rect() 中不需有空格,且取值不要带有不必要的 0
推荐:
.jdc {
color: rgba(255,255,255,.5);
}
不推荐:
.jdc {
color: rgba( 255, 255, 255, .5);
}
属性值十六进制数值能用简写的尽量用简写
推荐:
.jdc {
color: #fff;
}
不推荐:
.jdc {
color: #ffffff;
}
不要为 0 指明单位 推荐:
.jdc {
margin: 0 10px;
}
不推荐:
.jdc {
margin: 0px 10px;
}
属性
属性值引号
css属性值需要用到引号时,统一使用单引号
/* 推荐 */
.jdc {
font-family: 'Hiragino Sans GB';
}
/* 不推荐 */
.jdc {
font-family: "Hiragino Sans GB";
}
属性书写顺序
建议遵循以下顺序:
1,布局定位属性: display / position / float / clear / visibility / overflow 2, 自身属性:width / height / margin / padding / border / background 3, 文本属性: color / font / text-decoration / text-align / vertical-align / white-space / break-word 4, 其他属性(CSS3):content / cursor / border-radius / box-shadow /text-shadow / background:linear-gradient
.jdc {
display: block;
position: relative;
float: left;
width: 100px;
height: 100px;
margin: 0 10px;
padding: 20px 0;
font-family: Arial, 'Helvetica Neue', Helvetica, sans-serif;
color: #333;
background: rgba(0,0,0,.5);
-webkit-border-radius: 10px;
-moz-border-radius: 10px;
-o-border-radius: 10px;
-ms-border-radius: 10px;
border-radius: 10px;
}
CSS3浏览器私有前缀写法
CSS3浏览器私有前缀在前,标准前缀在后
.jdc {
-webkit-border-radius: 10px;
-moz-border-radius: 10px;
-o-border-radius: 10px;
-ms-border-radius: 10px;
border-radius: 10px;
}
JS规范
语言规范
JavaScript 是一种客户端脚本语言,这里列出了编写 JavaScript 时需要遵守的规则。
引用
const 和 let 都是块级作用域, var 是函数级作用域
// const 和 let 只存在于他们定义的块中
{
let a = 1
const b = 1
}
console.log(a) // ReferenceError
console.log(b) // ReferenceError
- 对所有引用都是用 const ,不要使用 var
原因:这样做可以确保你无法重新分配引用,以避免出现错误和难以理解的代码
// bad
var a = 1
var b = 2
// good
const a = 1
const b = 2
- 如果引用是可以变动的,使用 let 代替 var
原因: let 是块级作用域的,而不像 var 属于函数级作用域
// bad
var count = 1
if (count < 10) {
conut += 1
}
// good
let count = 1
if (count < 10) (
count += 1
)
对象
- 请使用字面量值创建对象
// bad
const a = new Object{}
// good
const a = {}
- 别使用保留字作为对象的键值,这样在 IE8 下不会运行
// bad
const a = {
default: {}, // default 是保留字
common: {}
}
// good
const a = {
defaults: {},
common: {}
}
- 当时用动态属性名创建对象时,请使用对象计算属性名来进行创建
原因:因为这样做就可以让你在一个地方定义所有的对象属性
function getKey(k) {
return `a key named ${k}`
}
// bad
const obj = {
id: 5,
name: 'San Francisco'
};
objp[getKey('enabled')] = true
// good
const obj = {
id: 5,
name: 'San Francisco',
[getKey('enabled')]: true
}
- 请使用对象方法的简写方式
// bad
const item = {
value: 1,
addValue: function (val) {
return item.value + val
}
}
// good
const item = {
value: 1,
addValue (val) {
return item.value + val
}
}
- 请使用对象属性值的简写方式
原因: 这样更简短且描述更清楚
const job = 'FrontEnd'
// bad
const item = {
job: job
}
// good
const item = {
job
}
- 将简写的对象属性分组后统一放到对象声明的开头
原因:这样更容易区分哪些属性用了简写的方式
const job = 'FrontEnd'
const department = 'JDC'
// bad
const item = {
sex: 'male',
job,
age: 25,
department
}
// good
const item = {
job,
department,
sex: 'male',
age: 25
}
- 只对非法标识符的属性使用引号
原因:因为通常来说我们认为这样主观上会更容易阅读,这样会带来代码高亮上的提升,同时也更容易被主流 JS 引擎优化
// bad
const bad = {
'foo': 3,
'bar': 4,
'data-blah': 5
}
// good
const good = {
foo: 3,
bar: 4,
'data-blah': 5
}
- 不要直接使用 Object.prototype 的方法,例如 hasOwnProperty, propertyIsEnumberable 和 isPrototypeOf 方法
原因:这些方法可能会被对象自身的同名属性覆盖 - 比如 { hasOwnProperty:false } 或者对象可能是一个 null 对象( Object.create(null))
// bad
console.log(object.hasOwnProperty(key))
// good
console.log(object.prototype.hasOwnProperty.call(object, key))
// best
const has = Object.prototype.hasOwnProperty // cache the lookup once, in module scope.
console.log(has.call(object, key)
)
/* or */
import has from 'has' // https://www.npmjs.com/package/has
console.log(has(object, key))
- 优先使用对象展开运算符 ... 来做对象浅拷贝而不是使用 Object.assgin, 使用对象剩余操作符来获得一个包含确定的剩余属性的新对象
// very bad
const original = { a: 1, b: 2 }
const copy = Object.assgin(original, { c: 3 }) // 会改变原始数组
// bad
const original = { a: 1, b: 2 }
const copy = Object.assgin({}, original, { c: 3 }) // copy => { a: 1, b: 2, c: 3}
// good
const original = { a: 1, b: 2 }
const copy = { ...original, c: 3} // copy => { a: 1, b: 2, c: 3 }
const { a, ...noA } = copy // noA => { b: 2, c: 3 }
数组
- 请使用字面量值创建数组
// bad
const items = new Array()
// good
const item = []
- 向数组中添加元素时,请使用 push 方法
const items = []
// bad
items[items.length] = 'test'
// good
items.push('test')
- 使用展开运算符 ... 复制数组
// bad
const items = []
const itemsCopy = []
const len = items.length
let i
// bad
for (i = 0; i < len; i++) {
itemsCopy[i] = items[i]
}
// good
itemsCopy = [...items]
- 把一个可迭代的对象转换为数组时,使用展开运算符 ... 而不是 Array.from
const foo = document.querySelectorAll('.foo')
// good
const nodes = Array.from(foo)
// best
const nodes = [...foo]
- 使用 Array.from 来将一个类数组对象转换为数组
const arrLike = { 0: 'foo', 1: 'bar', 2: 'baz', length: 3}
// bad
const arr = Array.prototype.slice.call(arrLike)
// good
const arr = Array.from(arrLike)
- 遍历迭代器进行映射时使用 Array.from 代替扩展运算符 ...,因为这可以避免创建中间数组
// bad
const baz = [...foo].map(bar)
// good
const baz = Array.from(foo, bar)
- 使用数组的 map 等方法时,请使用 return 声明,如果是单一声明语句的情况,可省略 return
// good
[1, 2, 3].map(x => {
const y = x + 1
return x * y
})
// good
[1, 2, 3].map(x => x + 1)
// bad
const flat = {}
[[0, 1], [2, 3], [4, 5]].reduce((memo, item, index) => {
const flatren = memo.concat(item)
flat[index] = flatren
})
// good
const flat = {}
[[0, 1], [2, 3], [4, 5]].reduce((memo, item, index) => {
const flatren = memo.concat(item)
flat[index] = flatren
return flatten
})
// bad
inbox.filter((msg) => {
const { subject, author } = msg
if (subject === 'Mockingbird') {
return author === 'Harper Lee'
} else {
return false
}
})
// good
inbox.filter((msg) => {
const { subject, author } = msg
if (subject === 'Mockingbird') {
return author === 'Harper Lee'
}
return false
})
- 如果一个数组有多行则要在数组的开括号后和闭括号前使用新行
// bad
const arr = [
[0, 1], [2, 3], [4, 5]
]
const objectInArray = [{
id: 1
}, {
id: 2
}]
const numberInArray = [
1, 2
]
// good
const arr = [[0, 1], [2, 3], [4, 5]]
const objectInArray = [
{
id: 1
},
{
id: 2
}
]
const numberInArray = [
1,
2
]
结构赋值
- 当需要使用对象的多个属性时,请使用结构赋值
第二层嵌套愿意:结构可以避免创建属性的临时引用
// bad
function getFullName (user) {
const firstName = user.firstName
const lastName = user.lastName
return `${firstName} ${lastName}`
}
// good
function getFullName (user) {
const { firstName, lastName } = user
return `${firstName} ${lastName}`
}
// better
function getFullName ({ firstName, lastName }) {
return `${firstName} ${lastName}`
}
- 当需要使用数组的多个值时,请同样使用结构赋值
const arr = [1, 2, 3, 4]
// bad
const first = arr[0]
const second = arr[1]
// good
const [first, second] = arr
-
函数需要回传多个值时,请使用对象的结构,而不是数组的结构
原因: 可以非破坏性地随时增加或者改变属性顺序
// bad
function doSomething () {
return [top, right, bottom, left]
}
// 如果是数组结构,那么在调用时就需要考虑数据的顺序
const [top, xx, xxx, left] = doSomething
// good
function doSomething () {
return {top, right, bottom, left}
}
// 此时不需要考虑数据的顺序
const { top, left } = doSomething
字符串
- 字符串统一使用单引号的形式 ''
// bad
const department = "JDC"
// good
const department = 'jdc'
- 字符串太长的时候,请不要使用字符串连接符换行 \ , 而是使用 +
const str = '凹凸实验室 凹凸实验室 凹凸实验室' +
'凹凸实验室 凹凸实验室 凹凸实验室' +
'凹凸实验室 凹凸实验室'
- 程序化生成字符串时,请使用模板字符串
const test = 'test'
// bad
cosnt str = ['a', 'b', test].join()
// bad
const str = 'a' + 'b' + test
// good
const str = `ab${test}`
- 不要对字符串使用 eval(), 会导致太多漏洞
- 不要在字符串中使用不必要的转义字符
// bad
const foo = '\'this\' \i\s \"quoted\"'
// good
const foo = '\'this\' is "quoted"'
const foo = `my name is '${name}'`
函数
- 不要使用 Function 构造函数创建函数
原因:此方式创建函数和对字符串使用 eval() 一样会产生漏洞
// bad
const add = new Function('a', 'b', 'return a + b')
// still bad
const subtract = Function('a', 'b', 'return a + b')
- 在函数签名中使用空格
// bad
const f = function(){}
const g = function (){}
const c = function() {}
// good
const x = function b () {}
const y = function c () {}
- 使用具名函数表达式而非函数声明
原因这样做会导致函数声明被提升,这意味着很容易在文件中定义此函数之前引用它,不利于可读性和可维护性。如果你发现函数定义既庞大又复杂以至于不能理解文件的其他部分,或许你应该将它拆分成模块!别忘记要显式命名表达式,而不用管名字是否是从包含的变量(通常出现在现代浏览器中或者使用 Babel 编译器的时候)中推断的。这样会消除错误调用堆栈中的任何假设。 (讨论)
// bad
function foo () {
// ...
}
// bad
const foo = function () {
// ...
}
// good
// lexical name distinguished from the variable-referenced invocation(s)
const short = function longUniqueMoreDescriptiveLexicalFoo () {
// ...
}
- 用圆括号包裹自执行匿名函数
原因:一个立即执行匿名函数表达式是一个单一的单元,将其及其调用括号包装在括号中,能够清楚地表达这一点。注意,在到处都是模块的世界中几乎不需要 IIFE。
// immediately-invoked function expression (IIFE)
(function () {
console.log('Welcome to the Internet. Please follow me.')
}())
- 不要在非函数代码块(if, while 等)中声明函数
// bad
if (isUse) {
function test () {
// do something
}
}
// good
let test
if (isUse) {
test = () => {
// do something
}
}
- 不要将参数命名为 arguments ,会导致该参数的优先级高于每个函数作用域内原先存在的 arguments 对象
// bad
function foo (name, options, arguments) {
// ...
}
// good
function foo (name, options, args) {
// ...
}
- 不要使用 arguments ,使用剩余运算符 ...
arguments 只是一个类数组,而 ... 是一个真正的数组
// bad
function test () {
const args = Array.prototype.slice.call(arguments)
return args.join('')
}
// good
function test (...args) {
return args.join('')
}
- 使用参数默认值语法而不是修改函数参数
// really bad
function handleThings (opts) {
// No! We shouldn't mutate function arguments.
// Double bad: if opts is falsy it'll be set to an object which may
// be what you want but it can introduce subtle bugs.
opts = opts || {}
// ...
}
// still bad
function handleThings (opts) {
if (opts === void 0) {
opts = {}
}
// ...
}
// good
function handleThings (opts = { }) {
// ...
}
- 避免参数默认值的副作用
let b = 1
// bad
function count (a = b++) {
console.log(a)
}
count() // 1
count() // 2
count(3) // 3
count() // 3
count() // 3
- 将参数默认值放在最后
// bad
function handleThings (opts = {}, name) {
// ...
}
// good
funtion handleThings (name, opts = {}) {
// ...
}
- 不要更改参数
原因:操作作为参数传入的对象可能在原始调用中造成意想不到的变量副作用
// bad
function f1 (obj) {
obj.key = 1
}
// godd
function f2 (obj) {
const key = Object.prototype.hasOwnProperty.call(obj, 'key') ? obj.key : 1
}
- 不要给参数重新赋值
原因:参数重新赋值可能会导致无法预期的行为,尤其是当操作 arguments 对象时,也可能导致优化问题,尤其是在 V8 引擎中
// bad
function f1 (a) {
a = 1
}
function f2 (a) {
if (!a) {
a = 1
}
}
// good
function f3 (a) {
const b = a || 1
}
function f4 (a = 1) {
}
- 调用可变参数函数时建议使用展开运算符 ...
原因:显然你无需使用上下文,很难结合 new 和 apply
// bad
const x = [1, 2, 3, 4, 5]
console.log.apply(console, x)
// good
const x = [1, 2, 3, 4, 5]
console.log(...x)
// bad
new (Function.prototype.bind.apply(Date, [null, 2016, 8, 5]))
// good
new Date(...[2016, 8, 5])
箭头函数
-
当你必须使用函数表达式(传递匿名函数)时,请使用箭头函数标记
原因:他将创建在 this 上下文中执行的函数版本,通常是您想要的,并且语法更简洁
如果您有一个相当复杂的函数,则可以将该逻辑移到其自己的命名函数表达式中
// bad
[1, 2, 3].map(function (x) {
const y = x + 1
return x * y
})
// good
[1, 2, 3].map((x) => {
const y = x + 1
return x * y
})
- 如果函数体只包含一条没有副作用的返回表达式的语句,可以省略花括号并使用隐式的 return,否则保留花括号并使用 return 语句
// bad
[1, 2, 3].map(number => {
const nextNumber = number + 1
`A string containing the ${nextNumber}.`
})
// good
[1, 2, 3].map(number => `A string containing the ${nextNumber}.`)
// good
[1, 2, 3].map((number) => {
const nextNumber = number + 1
return `A string containing the ${nextNumber}.`
})
// good
[1, 2, 3].map((number, index) => ({
index: number
}))
// No implicit return with side effects
function foo(callback) {
const val = callback()
if (val === true) {
// Do something if callback returns true
}
}
let bool = false
// bad
foo(() => bool = true)
// good
foo(() => {
bool = true
})
- 一旦表达式跨多行,使用圆括号包裹以便更好阅读
// bad
['get', 'post', 'put'].map(httpMethod => Object.prototype.hasOwnProperty.call(
httpMagicObjectWithAVeryLongName,
httpMethod
))
// good
['get', 'post', 'put'].map(httpMethod => (
Object.prototype.hasOwnProperty.call(
httpMagicObjectWithAVeryLongName,
httpMethod
)
))
- 函数如果只接收一个参数并且没使用花括号,则省略圆括号,否则为了清晰明确则使用圆括号包裹参数,注意:总是使用圆括号也是可以接受的
// bad
[1, 2, 3].map((x) => x * x)
// good
[1, 2, 3].map(x => x * x)
// good
[1, 2, 3].map(number => (
`A long string with the ${number}. It’s so long that we’ve broken it ` +
'over multiple lines!'
))
// bad
[1, 2, 3].map(x => {
const y = x + 1
return x * y
})
// good
[1, 2, 3].map((x) => {
const y = x + 1
return x * y
})
类&构造函数
- 使用 class ,避免直接操作 prototype
// bad
function Queue (contents = []) {
this._queue = [...contents]
}
Queue.prototype.pop = function () {
const value = this._queue[0]
this._queue.splice(0 , 1)
return value
}
// good
class Queue {
constructor (contents = []) {
this._queue = [...contents]
}
pop () {
const value = this._queue[0]
this._queue.splice(0, 1)
return value
}
}
- 使用 extends 来实现继承
原因:这是一个不会破坏 instanceof 的内建实现原型式继承的方式
// bad
const inherits = require('inherits')
function PeekableQueue(contents) {
Queue.apply(this, contents)
}
inherits(PeekableQueue, inherits)
PeekableQueue.prototype.peek = function () {
return this.queue[0]
}
// good
class PeekableQueue extends Queue {
peek () {
return this.queue[0]
}
}
- 如果未声明构造函数,则类会有一个默认的构造函数,没必要用空的构造函数或者将其委托给父类
// bad
class Jedi {
constructor () {}
getName() {
return this.name
}
}
// bad
class Rey extends Jedi {
constructor (...args) {
super(...args)
}
}
// good
class Rey extends Jedi {
constructor (...args) {
super(...args)
this.name = 'Rey'
}
}
- 避免类成员重复
原因:重复的类成员声明会默认使用最后声明的,通常会导致 bug
// bad
class Foo {
bar () { return 1 }
bar () { return 2 }
}
// good
class Foo {
bar () { return 1 }
}
// good
class
上一篇:
前端编码最佳实践大集合
下一篇:
终极指南: Vue 开发完全规范手册
推荐阅读
-
35 岁实现财务*,腾讯程序员手握2300万提前退休?-1000万房产、1000万腾讯股票、加上300万的现金,一共2300万的财产。有网友算了一笔账,假设1000万的房产用于自住,剩下1300万资产按照平均税后20-50万不等进行计算,大约花上26-60年左右的时间才能赚到这笔钱。也就是说,普通人可能奋斗一辈子,才能赚到这笔钱。在很多人还在为中年危机而惶惶不可终日的时候,有的人的35岁,就已经安全着陆,试问哪个打工人不羡慕?但问题是有这样财富积累必然有像样的实力做靠山。没有人可以不劳而获。
看到这里,肯定有人说,那么对于普通人来说,卷可能真就成了唯一的出路。但是卷也有轻松的卷,“偷懒”的卷法,对于程序员而言,刨除掉一时无法改掉的开会传统占用的大部分时间,如何把有限的时间和精力放在真正重要的架构设计、需求设计上,而不是重复的造*,编码、改bug、手动测试。因此在科技改变生活的今天,学会使用AI工具成为程序员们的必备技能。
以全栈式全自动的软件开发工具飞算SoFlu软件机器人为例,作为全球首款面向微服务架构设计和最佳实践的软件机器人,SoFlu软件机器人改变了原来手工编码的作业模式,通过可视化拖拽方式以及参数配置就能实现等同于编写复杂代码的业务逻辑,在设计业务逻辑时就完成了微服务应用开发,做到“业务即图,图即代码”,实现“软件开发,十倍提效”。
而作为飞算SoFlu软件机器人的一个重要组成部分,FuncGPT(慧函数)支持所有类型函数创建。通过自然语言描述Java函数需求,实时生成高质量、高可读性的Java函数代码。生成代码可直接复制到IDEA,或一键导入Java全自动开发工具函数库。
FuncGPT(慧函数)具有五大核心能力:
● 自然语言:通过自然语言即可生成函数,降低软件开发门槛。
● 秒级函数开发:全自动秒级开发函数,秒级完成,效率千倍提升。
● 一站式函数开发应用:函数生成即可直接应用,效率、安全有保障。
● 质量可靠:生成的函数代码符合业界规范、具备良好的可读性,符合最优解。
● 灵活生成:可以根据开发人员的具体需求生成并支持调整和修改。
以“将文件流转换为File对象”这个需求为例,以下是FuncGPT(慧函数)秒级生成的代码:
/ 类名:FileConverter
// 函数名:convertStreamToFile
// 函数功能:将文件流转换为File对象
// POM依赖包:无
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
public class FileConverter {
/**
* 将文件流转换为File对象
* @param inputStream 文件流
* @param filePath 文件路径
* @param fileName 文件名
* @return 转换后的File对象
* @throws IOException 如果发生I/O异常
*/
public static File convertStreamToFile(InputStream inputStream, String filePath, String fileName) throws IOException {
File file = new File(filePath + File.separator + fileName); // 创建File对象
try (FileOutputStream outputStream = new FileOutputStream(file)) { // 创建文件输出流
byte buffer = new byte[1024];
int bytesRead;
while ((bytesRead = inputStream.read(buffer)) != -1) { // 从文件流读取数据并写入文件
outputStream.write(buffer, 0, bytesRead);
}
}
return file; // 返回转换后的File对象
}
}
// 函数示例
// 将文件流转换为File对象示例
// 入参:inputStream,文件流
// 入参:filePath,文件路径
// 入参:fileName,文件名
// 出参:file,转换后的File对象
// 调用示例:
// InputStream inputStream = new FileInputStream("example.txt");
// String filePath = "C:\\Users\\User\\Documents";
// String fileName = "example.txt";
// File file = FileConverter.convertStreamToFile(inputStream, filePath, fileName);
// System.out.println(file.getAbsolutePath);
// 输出结果:例如,将文件流转换为File对象后,文件的绝对路径为:C:\Users\User\Documents\example.txt
// 则输出结果为:C:\Users\User\Documents\example.txt
通过分析,不难发现以上代码:
-
前端和后端协调的低代码开发--APICloud Studio 3 API 管理工具与数据云 3.0 结合使用教程
-
JavaScript 在各种源代码中的实现(前端面试笔试必备)
-
DataEase 开源代码在 Windows 系统开发环境中的设置和调试指南
-
一篇深入浅出的文章,介绍运行和维护开发的必备技能--HTML 表单。基础不牢,地动山摇。跟上节奏,复习巩固前端基础。
-
13 个强烈推荐的网络前端在线代码集成开发环境
-
.NET高级面试指南 Topic XVIII [ 介绍外观模式(Appearance Pattern),该模式提供了一个隐藏系统复杂性的简化界面 ]。- 简化复杂系统:当系统具有复杂的子系统结构时,可以使用外观模式来简化界面。提供统一界面:当客户端需要访问多个子系统时,可以使用外观模式提供统一界面。
外观模式在现代软件开发中得到广泛应用,尤其是在复杂系统中。例如
图形用户界面库:许多图形用户界面库(如 Qt、GTK+ 等)都使用外观模式来隐藏底层的复杂性,并为开发人员提供简单的界面来创建用户界面。
操作系统接口:操作系统中的系统调用和应用程序接口通常也使用外观模式来隐藏底层硬件和系统的复杂性,为应用程序提供访问系统资源的简单接口。企业应用程序:在可能涉及多个子系统的大型企业应用程序中,外观模式可用于封装这些子系统,并为客户端提供统一的使用界面。
网络框架:许多网络框架(如 ASP.NET MVC、Spring MVC 等)也使用外观模式来隐藏底层的复杂性,并为开发人员提供简单的接口来处理 HTTP 请求和响应。
集成开发环境(IDE):集成开发环境通常包含代码编辑器、编译器、调试器等多种功能。外观模式可用于封装这些功能,并为开发人员提供开发软件的简单界面。
代码示例:
-
前端开发规范指南:构建优雅代码
-
[代码规范] Web 前端开发规范文件!
-
制定有效的开发规范:提高团队合作和代码质量的关键策略