我们在这里学习的是生成随机数,在固定区间内生成随机整数的公式为:
Math.floor(Math.random()*(max-min+1))+min;
法典
初始要求是猜测 1-10 范围内的数字
代码如下:
<script>
function getRandom(min, max) {
return Math.floor(Math.random() * (max - min + 1)) + min;
}
var random = getRandom(1, 10);
while(true) {
var num = prompt('你来猜,输入1-10之间一个数字,你有' + (count - i) + '次机会');
if (num > random) {
alert('你猜大了');
} else if (num < random) {
alert('你猜小了');
} else {
alert('恭喜你,猜对了');
break;
}
}
</script>
为了进一步提高javascript猜数字游戏,只给3次猜测的机会(次数可以自己给出)javascript猜数字游戏,更改如下
<script>
var count = 3;
var num = -1;
var random = getRandom(1, 10);
function getRandom(min, max) {
return Math.floor(Math.random() * (max - min + 1)) + min;
}
for (var i = 0; i < count; i++) {
var num = prompt('你来猜,输入1-10之间一个数字,你有' + (count - i) + '次机会');
if (num > random) {
alert('你猜大了');
} else if (num < random) {
alert('你猜小了');
} else {
break;
}
}
if (num == random) {
alert('你猜对了');
}
else {
alert('机会用完了!')
}
</script>
脚本屋
您与数百万开发者同在
来源/javascript
现在写代码比以前好多了。 代码的格式由eslint、prettier、babel(编写新句型)来保证。 然而,无论技术手段多么先进,都无法解决代码可读性(代码可以被未来的自己和朋友阅读。理解),因为只有人才能解决。 我们把代码写到右图右边,这样功德就基本完整了。
注:由于个人水平和视野,本文并没有完全涵盖常见的编写代码的坏习惯,所以如果您觉得需要补充,可以在文章下方评论,或者直接到我的评论这篇文章GitHub。 对于那些有用的,它们将添加到我的鹈鹕和 Github 中。 同时javascript是什么意思,如果您觉得文章写得不错,请在我的Github上发送您宝贵的Star。 您的Star是我继续写文章的最大动力。
1.变量相关性
(1) 变量个数的定义
否:滥用变量:
let kpi = 4; // 定义好了之后再也没用过
function example() {
var a = 1;
var b = 2;
var c = a+b;
var d = c+1;
var e = d+a;
return e;
}
YES:数据仅使用一次或在未加载到变量中时不使用
let kpi = 4; // 没用的就删除掉,不然过三个月自己都不敢删,怕是不是那用到了
function example() {
var a = 1;
var b = 2;
return 2a+b+1;
}
(2)变量的命名
NO:自我感觉良好的简写
let fName = 'jackie'; // 看起来命名挺规范,缩写,驼峰法都用上,ESlint各种检测规范的工具都通过,But,fName是啥?这时候,你是不是想说What are you 弄啥呢?
let lName = 'willen'; // 这个问题和上面的一样
YES:不需要为每个变量写注释,只需从名称中读取即可
let firstName = 'jackie'; // 怎么样,是不是一目了然。少被喷了一次
let lastName = 'willen';
(3) 具体变量
NO:无说明的参数
if (value.length < 8) { // 为什么要小于8,8表示啥?长度,还是位移,还是高度?Oh,my God!!
....
}
是:添加变量
const MAX_INPUT_LENGTH = 8;
if (value.length < MAX_INPUT_LENGTH) { // 一目了然,不能超过最大输入长度
....
}
(4)变量的命名
NO:命名太罗嗦
let nameString;
let theUsers;
是:保持简单明了
let name;
let users;
(5)使用描述性变量(即有意义的变量名)
NO:我不知道长代码是什么意思
const address = 'One Infinite Loop, Cupertino 95014';
const cityZipCodeRegex = /^[^,]+[,s]+(.+?)s*(d{5})?$/;
saveCityZipCode(
address.match(cityZipCodeRegex)[1], // 这个公式到底要干嘛,对不起,原作者已经离职了。自己看代码
address.match(cityZipCodeRegex)[2], // 这个公式到底要干嘛,对不起,原作者已经离职了。自己看代码
);
YES:使用变量名来解释长代码的含义
const address = 'One Infinite Loop, Cupertino 95014';
const cityZipCodeRegex = /^[^,]+[,s]+(.+?)s*(d{5})?$/;
const [, city, zipCode] = address.match(cityZipCodeRegex) || [];
saveCityZipCode(city, zipCode);
(6)避免使用过多的全局变量
NO:在不同文件中不断定义全局变量
name.js
window.name = 'a';
hello.js
window.name = 'b';
time.js
window.name = 'c'; //三个文件的先后加载顺序不同,都会使得window.name的值不同,同时,你对window.name的修改了都有可能不生效,因为你不知道你修改过之后别人是不是又在别的说明文件中对其的值重置了。所以随着文件的增多,会导致一团乱麻。
是:少用或使用替代方案您可以选择仅使用局部变量。 通过 (){}。
如果你确实用很多的全局变量需要共享,你可以使用vuex,redux或者你自己参考flux模式写一个也行。
(7) 变量的形式参数。
NO:对于评估得到的变量,没有底线。
const MIN_NAME_LENGTH = 8;
let lastName = fullName[1];
if(lastName.length > MIN_NAME_LENGTH) { // 这样你就给你的代码成功的埋了一个坑,你有考虑过如果fullName = ['jackie']这样的情况吗?这样程序一跑起来就爆炸。要不你试试。
....
}
是:对于评价变量,做好覆盖底线工作。
const MIN_NAME_LENGTH = 8;
let lastName = fullName[1] || ''; // 做好兜底,fullName[1]中取不到的时候,不至于赋值个undefined,至少还有个空字符,从根本上讲,lastName的变量类型还是String,String原型链上的特性都能使用,不会报错。不会变成undefined。
if(lastName.length > MIN_NAME_LENGTH) {
....
}
其实在项目中有很多求值变量,对于每个求值变量都需要做好兜底。
let propertyValue = Object.attr || 0; // 因为Object.attr有可能为空,所以需要兜底。
但是,赋值变量就不需要兜底了。
let a = 2; // 因为有底了,所以不要兜着。
let myName = 'Tiny'; // 因为有底了,所以不要兜着。
二、功能相关
(1)函数命名
NO:从名称无法得知返回值类型
function showFriendsList() {....} // 现在问,你知道这个返回的是一个数组,还是一个对象,还是true or false。你能答的上来否?你能答得上来我请你吃松鹤楼的满汉全席还请你不要当真。
是:对于返回true或false的函数,最好以should/is/can/has开头
function shouldShowFriendsList() {...}
function isEmpty() {...}
function canCreateDocuments() {...}
function hasLicense() {...}
(2)函数函数最好是纯函数
NO:不要让功能函数的输出变化无常。
function plusAbc(a, b, c) { // 这个函数的输出将变化无常,因为api返回的值一旦改变,同样输入函数的a,b,c的值,但函数返回的结果却不一定相同。
var c = fetch('../api');
return a+b+c;
}
YES:泛函函数使用纯函数javascript是什么意思,输入一致,输出结果始终唯一
function plusAbc(a, b, c) { // 同样输入函数的a,b,c的值,但函数返回的结果永远相同。
return a+b+c;
}
(3)函数参数传递
NO:没有参数传递的描述
page.getSVG(api, true, false); // true和false啥意思,一目不了然
YES:有传递参数的说明
page.getSVG({
imageApi: api,
includePageBackground: true, // 一目了然,知道这些true和false是啥意思
compress: false,
})
(4) 动作函数必须以介词开头
NO:无法判断函数意图
function emlU(user) {
....
}
YES:在动词开头,功能的意图很明显
function sendEmailToUser(user) {
....
}
(5)一个功能完成一个独立的功能,不要将多个功能与一个功能混合
这是软件工程最重要的规则之一,当函数要做的事情越多时,它们就越难编写、测试、理解和组合。 当您可以抽象出一个函数来仅执行一个操作时,它们将更易于构造,并且您的代码将更易于阅读。 如果你严格遵守这个规则,你就会领先于很多开发者。
NO:功能混乱,一个功能包含多个功能。 最后被乱拳砍死(乱拳(复杂功能)杀了老夫子(老程序员))
function sendEmailToClients(clients) {
clients.forEach(client => {
const clientRecord = database.lookup(client)
if (clientRecord.isActive()) {
email(client)
}
})
}
YES:功能拆解,
function sendEmailToActiveClients(clients) { //各个击破,易于维护和复用
clients.filter(isActiveClient).forEach(email)
}
function isActiveClient(client) {
const clientRecord = database.lookup(client)
return clientRecord.isActive()
}
(6)优先使用函数式编程
NO:用于循环编程
for(i = 1; i <= 10; i++) { // 一看到for循环让人顿生不想看的情愫
a[i] = a[i] +1;
}
是:使用函数式编程
let b = a.map(item => ++item) // 怎么样,是不是很好理解,就是把a的值每项加一赋值给b就可以了。现在在javascript中几乎所有的for循环都可以被map,filter,find,some,any,forEach等函数式编程取代。
(7) 过多使用if else ..
否:太多 if else
if (a === 1) {
...
} else if (a ===2) {
...
} else if (a === 3) {
...
} else {
...
}
YES:可以用switch或者链表代替
switch(a) {
case 1:
....
case 2:
....
case 3:
....
default:
....
}
Or
let handler = {
1: () => {....},
2: () => {....}.
3: () => {....},
default: () => {....}
}
handler[a]() || handler['default']()
3.尽量使用ES6,如果可以的话,ES7中的新句型(只列出了最常用的新句型,说实话,有些新句型不是很常用)
(1)尝试使用箭头函数
否:使用传统功能
function foo() {
// code
}
是:使用箭头函数
let foo = () => {
// code
}
(2) 连接字符串
否:使用传统的+号
var message = 'Hello ' + name + ', it's ' + time + ' now'
是:使用模板字符
var message = `Hello ${name}, it's ${time} now`
(3) 使用重构参数
否:使用传统参数:
var data = { name: 'dys', age: 1 };
var name = data.name;
var age = data.age;
var fullName = ['jackie', 'willen'];
var firstName = fullName[0];
var lastName = fullName[1];
是:使用结构参数:
const data = {name:'dys', age:1};
const {name, age} = data; // 怎么样,是不是简单明了
var fullName = ['jackie', 'willen'];
const [firstName, lastName] = fullName;
(4)尝试使用class类
NO:使用传统的函数原型链来实现继承
典型的 ES5 的类(function)在继承、构造和方法定义方面可读性较差,当需要继承时,优先选用 class。代码太多,就省略了。
YES:使用ES6类来实现继承
class Animal {
constructor(age) {
this.age = age
}
move() {
/* ... */
}
}
class Mammal extends Animal {
constructor(age, furColor) {
super(age)
this.furColor = furColor
}
liveBirth() {
/* ... */
}
}
class Human extends Mammal {
constructor(age, furColor, languageSpoken) {
super(age, furColor)
this.languageSpoken = languageSpoken
}
speak() {
/* ... */
}
}
先说这个吧,这是目前为止发现的问题,这篇文章并没有完全涵盖常见的写代码的坏习惯,所以如果你觉得有什么补充的,可以在文章下面评论,或者直接去我的 Github 对这篇文章发表评论。 对于那些有用的,它们将添加到我的鹈鹕和 Github 中。 同时,如果您觉得文章写得不错,请在我的Github上发送您宝贵的Star。 您的Star是我继续写文章的最大动力。
注:除了上述这些人为习惯之外,就像前面提到的,对于机械性的,你可以使用Babel、Eslint、Prettier这些工具来保证代码的格式一致。
参考
(JavaScript 干净编码最佳实践)
(如何写出漂亮的JavaScript代码?)
结尾