autojs代码规范

简介: autojs代码规范

原则

  • 能用
  • 易读
  • 短路优先:
  • 函数尽可能短,太长的函数拆分
  • 控制块尽可能短,太长的控制块抽出函数
  • 条件判断时,短分支写在长分支前面
  • 变量声明和变量使用的间隔尽可能地短
  • 变量的作用域尽可能的短
  • 得到返回值尽可能早的return,清理操作放finally
  • 发现异常尽可能早的throw,哪怕catch再rethrow
  • 对称: 有上就有下,有左就有右, 有主动就有被动
  • 命名对称: set/get、start/stop、begin/ end 和 push/pop
  • 条件与反条件
  • 层次: 主从关系、前后关系和本末关系, 不同层次各司其职,同种处理不跨越多个层次
  • 安全: 在编写代码时刻意将不可能的条件考虑进去
  • 好名字 > 坏名字 + 注释
  • 缓存常用的值


插件


vscode必须安装插件Prettier - Code formatter, 格式化代码快捷键 Shift + Alt + F


Prettier is an opinionated code formatter. It enforces a consistent style by parsing your code and re-printing it with its own rules that take the maximum line length into account, wrapping code when necessary.


文档注释

各类标签@param, @method等请参考usejsdocJSDoc Guide

/**
 * @func
 * @desc 一个带参数的函数
 * @param {string} a - 参数a
 * @param {number} b=1 - 参数b默认值为1
 * @param {string} c=1 - 参数c有两种支持的取值</br>1—表示x</br>2—表示xx
 * @param {object} d - 参数d为一个对象
 * @param {string} d.e - 参数d的e属性
 * @param {string} d.f - 参数d的f属性
 * @param {object[]} g - 参数g为一个对象数组
 * @param {string} g.h - 参数g数组中一项的h属性
 * @param {string} g.i - 参数g数组中一项的i属性
 * @param {string} [j] - 参数j是一个可选参数
 */
function foo(a, b, c, d, g, j) {
    ...
}


变量命名

  • 标准变量采用驼峰式命名(除了对象的属性外,主要是考虑到cgi返回的数据)
  • 'ID'在变量名中全大写
  • 'URL'在变量名中全大写
  • 'Android'在变量名中大写第一个字母
  • 'iOS'在变量名中小写第一个,大写后两个字母
  • 常量全大写,用下划线连接
  • 构造函数,大写第一个字母
  • jquery对象必须以'$'开头命名
var thisIsMyName;
var goodID;
var reportURL;
var AndroidVersion;
var iOSVersion;
var MAX_COUNT = 10;
function Person(name) {
    this.name = name;
}
// not good
var body = $('body');
// good
var $body = $('body');


变量声明

一个函数作用域中所有的变量声明尽量提到函数首部,用一个var声明,不允许出现两个连续的var声明。

function doSomethingWithItems(items) {
    // use one var
    var value = 10,
        result = value + 10,
        i,
        len;
    for (i = 0, len = items.length; i < len; i++) {
        result += 10;
    }
}


null

适用场景:

  • 初始化一个将来可能被赋值为对象的变量
  • 与已经初始化的变量做比较
  • 作为一个参数为对象的函数的调用传参
  • 作为一个返回对象的函数的返回值

不适用场景:

  • 不要用null来判断函数调用时有无传参
  • 不要与未初始化的变量做比较
// not good
function test(a, b) {
    if (b === null) {
        // not mean b is not supply
        ...
    }
}
var a;
if (a === null) {
    ...
}
// good
var a = null;
if (a === null) {
    ...
}


undefined

永远不要直接使用undefined进行变量判断;

使用typeof和字符串'undefined'对变量进行判断。

// not good
if (person === undefined) {
    ...
}
// good
if (typeof person === 'undefined') {
    ...
}


格式化字符串

obj = {
  name: "牙叔教程",
  add(a, b) {
    return a + b;
  },
};
r = util.format("数字%d, 文本: %s, 对象%j", 1, "abc", obj);
console.log(r);
// 数字1, 文本: abc, 对象{"name":"牙叔教程"} 


模块测试

"use strict";
function add(num1, num2) {
  return num1 + num2;
}
let obj = {
  name: "牙叔教程",
  add: add,
};
if (typeof module === "undefined") {
  let r = obj.add(1, 2);
  console.log(r);
} else {
  module.exports = obj;
}


importClass和require谁先谁后

runtime.loadDex("./yashu.dex");
importClass(android.graphics.Rect);
let yashu = require("./yashu");


  • 提示框和提示信息,例如 showDialog
  • updateXX:更新某个东西,例如 updateData
  • saveXX:保存某个东西,例如 saveData
  • resetXX:重置某个东西,例如 resetData
  • clearXX:清除某个东西,例如 clearData
  • removeXX:移除数据或者视图等,例如 removeView
  • drawXX:绘制数据或效果相关的,使用 draw 前缀标识,例如 drawText


  • 避免单个字符名,让你的变量名有描述意义。
// bad
function q() {
  // ...stuff...
}
// good
function query() {
  // ..stuff..
}


当命名对象、函数和实例时使用驼峰命名规则

// bad
var OBJEcttsssss = {};
var this_is_my_object = {};
var this-is-my-object = {};
function c() {};
var u = new user({
  name: 'Bob Parr'
});
// good
var thisIsMyObject = {};
function thisIsMyFunction() {};
var user = new User({
  name: 'Bob Parr'
});


  • 当命名构造函数或类时使用驼峰式大写
// bad
function user(options) {
  this.name = options.name;
}
var bad = new user({
  name: 'nope'
});
// good
function User(options) {
  this.name = options.name;
}
var good = new User({
  name: 'yup'
});


  • 命名私有属性时前面加个下划线 _
// bad
this.__firstName__ = 'Panda';
this.firstName_ = 'Panda';
// good
this._firstName = 'Panda';


当保存对 this 的引用时使用 _this.v

// bad
function() {
  var self = this;
  return function() {
    console.log(self);
  };
}
// bad
function() {
  var that = this;
  return function() {
    console.log(that);
  };
}
// good
function() {
  var _this = this;
  return function() {
    console.log(_this);
  };
}


文件命名规范


  • 谷歌

File names must be all lowercase and may include underscores (_) or dashes (-), but no additional punctuation. Follow the convention that your project uses. Filenames’ extension must be .js.

  • github

What is the javascript filename naming convention?

  • 其他1


Js 文件命名规范


  • 字母全部小写
  • 不要带空格
  • 用破折号(-)连接单词
  • 库文件可用逗点(.),用于体现版本或从属关系


Demo


  • vue.min.js
  • vue-router.js
  • jquery.form.js
  • jquery-1.4.2.min.js


  • 其他2

1、项目命名

全部采用小写方式,以下划线分割战场
例如:come_money

2、目录命名

参照项目命名,如有复数结构时,采用复数命名法
例如: moneys,assets,components。。。。

3、js、css、less、sass、 stylus文件命名

全部采用小驼峰命名规则
例如: comeMoney.js、moneyCome.css、moneyCome.stylus

4、VUE组件Components命名

所有组件名字大驼峰格式
例如: ComeMoney.vue、MoneyCome.vue

  • 上面的惯例仅供参考,最终还是尊重个人习惯。不过如果你在项目中引用了某个框架或库,就最好优先使用他们的命名习惯。另外,一个项目中最好统一使用一种命名规则,这样方便自己和其他开发人员识别。


对象


  • 请使用对象方法的简写方式, 属性不可简写, 方法可以简写
// bad
const item = {
  value: 1,
  addValue: function (val) {
    return item.value + val
  }
}
// good
const item = {
  value: 1,
  addValue (val) {
    return item.value + val
  }
}


  • 不要直接使用 Object.prototype 的方法, 例如 hasOwnProperty, propertyIsEnumerableisPrototypeOf 方法


原因:这些方法可能会被对象自身的同名属性覆盖 - 比如 { 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))


数组


  • 当你需要拷贝数组时使用slice
var len = items.length,
    itemsCopy = [],
    i;
// bad
for (i = 0; i < len; i++) {
  itemsCopy[i] = items[i];
}
// good
itemsCopy = items.slice();


使用slice将类数组的对象转成数组

function trigger() {
  var args = Array.prototype.slice.call(arguments);
  ...
}


解构赋值


  • 当需要使用数组的多个值时,请使用解构赋值
const arr = [1, 2, 3, 4]
// bad
const first = arr[0]
const second = arr[1]
// good
const [first, second] = arr


字符串


  • 字符串太长的时候,请不要使用字符串连接符换行 \,而是使用 +
const str = '牙叔教程 牙叔教程 牙叔教程' +
  '牙叔教程 牙叔教程 牙叔教程' +
  '牙叔教程 牙叔教程'


不要在字符串中使用不必要的转义字符

// bad
const foo = '\'this\' \i\s \"quoted\"'
// good
const foo = '\'this\' is "quoted"'


编程时使用join而不是字符串连接来构建字符串

var items,
    messages,
    length, i;
messages = [{
    state: 'success',
    message: 'This one worked.'
},{
    state: 'success',
    message: 'This one worked as well.'
},{
    state: 'error',
    message: 'This one did not work.'
}];
length = messages.length;
// bad
function inbox(messages) {
  items = '<ul>';
  for (i = 0; i < length; i++) {
    items += '<li>' + messages[i].message + '</li>';
  }
  return items + '</ul>';
}
// good
function inbox(messages) {
  items = [];
  for (i = 0; i < length; i++) {
    items[i] = messages[i].message;
  }
  return '<ul><li>' + items.join('</li><li>') + '</li></ul>';
}


函数


  • 函数表达式
// 匿名函数表达式
var anonymous = function() {
  return true;
};
// 有名函数表达式
var named = function named() {
  return true;
};
// 立即调用函数表达式
(function() {
  console.log('Welcome to the Internet. Please follow me.');
})();


用圆括号包裹自执行匿名函数

(function () {
  console.log('Welcome to the Internet. Please follow me.')
}())


  • 不要在一个非函数块里声明一个函数,把那个函数赋给一个变量。

注: ECMA-262定义把定义为一组语句,函数声明不是一个语句。阅读ECMA-262对这个问题的说明.

// bad
if (currentUser) {
  function test() {
    console.log('Nope.');
  }
}
// good
if (currentUser) {
  var test = function test() {
    console.log('Yup.');
  };
}


绝对不要把参数命名为 arguments, 这将会逾越函数作用域内传过来的 arguments 对象.

// bad
function nope(name, options, arguments) {
  // ...stuff...
}
// good
function yup(name, options, args) {
  // ...stuff...
}


箭头函数


  • 当你必须使用函数表达式(传递匿名函数)时,使用箭头函数标记
// 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
})


对象属性


  • 使用 . 来访问对象属性
const joke = {
  name: 'haha',
  age: 28
}
// bad
const name = joke['name']
// good
const name = joke.name


当访问的属性是变量时使用 []

const luke = {
  jedi: true,
  age: 28,
}
function getProp (prop) {
  return luke[prop]
}
const isJedi = getProp('jedi')


变量声明


  • 在作用域顶部声明变量,避免变量声明和赋值引起的相关问题。
// bad
function() {
  test();
  console.log('doing stuff..');
  //..other stuff..
  var name = getName();
  if (name === 'test') {
    return false;
  }
  return name;
}
// good
function() {
  var name = getName();
  test();
  console.log('doing stuff..');
  //..other stuff..
  if (name === 'test') {
    return false;
  }
  return name;
}
// bad
function() {
  var name = getName();
  if (!arguments.length) {
    return false;
  }
  return true;
}
// good
function() {
  if (!arguments.length) {
    return false;
  }
  var name = getName();
  return true;
}


  • 将所有的 constlet 分组
// bad
let a
const b
let c
const d
let e
// good
const b
const d
let a
let c
let e


变量不要进行链式赋值  
原因:变量链式赋值会创建隐藏的全局变量

// bad
(function example() {
  // JavaScript interprets this as
  // let a = ( b = ( c = 1 ) );
  // The let keyword only applies to variable a; variables b and c become
  // global variables.
  let a = b = c = 1
}())
console.log(a) // throws ReferenceError
console.log(b) // 1
console.log(c) // 1
// good
(function example() {
  let a = 1
  let b = a
  let c = a
}())
console.log(a) // throws ReferenceError
console.log(b) // throws ReferenceError
console.log(c) // throws ReferenceError
// the same applies for `const`


  • 不允许出现未被使用的变量

原因:声明但未被使用的变量通常是不完全重构犯下的错误.这种变量在代码里浪费空间并会给读者造成困扰

// bad
var some_unused_var = 42
// Write-only variables are not considered as used.
var y = 10
y = 5
// A read for a modification of itself is not considered as used.
var z = 0
z = z + 1
// Unused function arguments.
function getX (x, y) {
  return x
}
// good
function getXPlusY (x, y) {
  return x + y
}
const x = 1
const y = a + 2
alert(getXPlusY(x, y))
// 'type' is ignored even if unused because it has a rest property sibling.
// This is a form of extracting an object that omits the specified keys.
const { type, ...coords } = data
// 'coords' is now the 'data' object without its 'type' property.


Hoisting


  • var 存在变量提升的情况,即 var 声明会被提升至该作用域的顶部,但是他们的赋值并不会。而 constlet 并不存在这种情况,他们被赋予了 Temporal Dead Zones, TDZ, 了解 typeof 不再安全很重要
function example () {
  console.log(notDefined)   // => throws a ReferenceError
}
function example () {
  console.log(declareButNotAssigned)  // => undefined
  var declaredButNotAssigned = true
}
function example () {
  let declaredButNotAssigned
  console.log(declaredButNotAssigned)   // => undefined
  declaredButNotAssigned = true
}
function example () {
  console.log(declaredButNotAssigned)   // => throws a ReferenceError
  console.log(typeof declaredButNotAssigned)  // => throws a ReferenceError
  const declaredButNotAssigned = true
}


匿名函数的变量名会提升,但函数内容不会

function example () {
  console.log(anonymous)  // => undefined
  anonymous()
  var anonymous = function () {
    console.log('test')
  }
}


命名的函数表达式的变量名会被提升,但函数名和函数函数内容并不会

function example() {
  console.log(named)  // => undefined
  named()   // => TypeError named is not a function
  superPower()  // => ReferenceError superPower is not defined
  var named = function superPower () {
    console.log('Flying')
  }
}
function example() {
  console.log(named)  // => undefined
  named()   // => TypeError named is not a function
  var named = function named () {
    console.log('named')
  }
}


比较运算符&相等


  • 使用 ===!== 而非 ==!=,eslint: eqeqeq
  • 条件声明例如 if 会用 ToBoolean 这个抽象方法将表达式转成布尔值并遵循如下规则
  • Objects 等于 true
  • Undefined 等于 false
  • Null 等于 false
  • Booleans 等于 布尔值
  • Numbers+0, -0, 或者 NaN 的情况下等于 false, 其他情况是 true
  • Strings'' 时等于 false, 否则是 true
if ([0] && []) {
  // true
  // 数组(即使是空数组)也是对象,对象等于true
}
// bad
if (name !== '') {
  // ...stuff...
}
// good
if (name) {
  // ...stuff...
}
// bad
if (collection.length > 0) {
  // ...stuff...
}
// good
if (collection.length) {
  // ...stuff...
} 


分号


  • 自执行函数前后必须加分号
const test = '牙叔教程'
;(() => {
  const str = '简单易学'
})();



  • 给所有多行的块使用大括号
// bad
if (test)
  return false;
// good
if (test) return false;
// good
if (test) {
  return false;
}
// bad
function() { return false; }
// good
function() {
  return false;
}


注释


  • 使用 /** ... */ 进行多行注释,包括描述,指定类型以及参数值和返回值
// bad
// make() returns a new element
// based on the passed in tag name
//
// @param <String> tag
// @return <Element> element
function make(tag) {
  // ...stuff...
  return element;
}
// good
/**
 * make() returns a new element
 * based on the passed in tag name
 *
 * @param <String> tag
 * @return <Element> element
 */
function make(tag) {
  // ...stuff...
  return element;
}


使用 // 进行单行注释,在评论对象的上面进行单行注释,注释前放一个空行.

// bad
var active = true;  // is current tab
// good
// is current tab
var active = true;
// bad
function getType() {
  console.log('fetching type...');
  // set the default type to 'no type'
  var type = this._type || 'no type';
  return type;
}
// good
function getType() {
  console.log('fetching type...');
  // set the default type to 'no type'
  var type = this._type || 'no type';
  return type;
}


如果你有一个问题需要重新来看一下或如果你建议一个需要被实现的解决方法的话需要在你的注释前面加上 FIXMETODO 帮助其他人迅速理解

function Calculator() {
  // FIXME: shouldn't use a global here
  total = 0;
  return this;
}
function Calculator() {
  // TODO: total should be configurable by an options param
  this.total = 0;
  return this;
}


存取器


  • 属性的存取器函数不是必需的
  • 如果你确实有存取器函数的话使用getVal() 和 setVal('hello')
// bad
dragon.age();
// good
dragon.getAge();
// bad
dragon.age(25);
// good
dragon.setAge(25);


如果属性是布尔值,使用isVal() 或 hasVal()

// bad
if (!dragon.age()) {
  return false;
}
// good
if (!dragon.hasAge()) {
  return false;
}


可以创建get()和set()函数,但是要保持一致

function Jedi(options) {
  options || (options = {});
  var lightsaber = options.lightsaber || 'blue';
  this.set('lightsaber', lightsaber);
}
Jedi.prototype.set = function(key, val) {
  this[key] = val;
};
Jedi.prototype.get = function(key) {
  return this[key];
};


构造器


  • 给对象原型分配方法,而不是用一个新的对象覆盖原型,覆盖原型会使继承出现问题。
function Jedi() {
  console.log('new jedi');
}
// bad
Jedi.prototype = {
  fight: function fight() {
    console.log('fighting');
  },
  block: function block() {
    console.log('blocking');
  }
};
// good
Jedi.prototype.fight = function fight() {
  console.log('fighting');
};
Jedi.prototype.block = function block() {
  console.log('blocking');
};


方法可以返回 this 帮助方法可链。

// bad
Jedi.prototype.jump = function() {
  this.jumping = true;
  return true;
};
Jedi.prototype.setHeight = function(height) {
  this.height = height;
};
var luke = new Jedi();
luke.jump(); // => true
luke.setHeight(20) // => undefined
// good
Jedi.prototype.jump = function() {
  this.jumping = true;
  return this;
};
Jedi.prototype.setHeight = function(height) {
  this.height = height;
  return this;
};
var luke = new Jedi();
luke.jump()
  .setHeight(20);


可以写一个自定义的toString()方法,但是确保它工作正常并且不会有副作用。

function Jedi(options) {
  options || (options = {});
  this.name = options.name || 'no name';
}
Jedi.prototype.getName = function getName() {
  return this.name;
};
Jedi.prototype.toString = function toString() {
  return 'Jedi - ' + this.getName();
};


参考

Google JavaScript Style Guide

aotu前端代码规范

javascriptCodeStyle

Android 代码规范文档

高质量代码编程的原则

为何部分程序员从不使用 break 或 continue 语句?

Code Guide by @AlloyTeam


名人名言

思路是最重要的, 其他的百度, bing, stackoverflow, 安卓文档, autojs文档, 最后才是群里问问

--- 牙叔教程


声明

部分内容来自网络

本教程仅用于学习, 禁止用于其他用途










相关文章
|
7月前
|
API
AutoJs4.1.0开发心得
AutoJs4.1.0开发心得
100 0
|
7月前
|
SQL 存储 安全
代码规范(如何提高代码规范)
在软件开发中,优雅的代码规范对于编写美观且实用的代码至关重要。以下是一些提升代码质量的建议: 1. **命名清晰**:使用描述性强的命名,使代码自解释,减少误解,提高可读性。 2. **简洁性**:用最少的代码实现功能,避免冗余,简洁的代码更易维护。 3. **一致性**:保持命名和编码风格的一致性,降低团队协作成本。 4. **注释**:合理注释解释代码意图,但避免过度注释。 5. **避免复杂性**:将复杂逻辑分解为简单部分,用函数或模块封装。 6. **重构**:定期重构代码以提高可读性和性能。 7. **测试**:编写单元测试确保代码的稳定性和可靠性。
|
7月前
|
数据库
代码规范(一)
代码规范(一)
64 0
|
7月前
|
缓存 Python
最后一次AutoJs超神级代码分享
最后一次AutoJs超神级代码分享
128 0
|
存储 JavaScript Unix
[笔记]c++Windows平台代码规范(下)
[笔记]c++Windows平台代码规范(下)
154 0
|
安全 Linux C++
[笔记]c++Windows平台代码规范(上)
[笔记]c++Windows平台代码规范
158 0
|
C语言
代码规范要求
代码规范要求
173 0
16 条 yyds 的代码规范 下
16 条 yyds 的代码规范 下
162 0
16 条 yyds 的代码规范   下