原生JS | 当兔子遇到鸡

时间:2022-05-04
本文章向大家介绍原生JS | 当兔子遇到鸡,主要内容包括其使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。
HTML5学堂-码匠:当兔子遇到鸡,会怎样呢?先别急,看个小视频~
视频内容

当兔子遇到鸡 —— 不要害怕和别人不一样,在这个世界上,你就是独一无二的自己!

不知道有多少程序在看到这个小视频的时候,想到的不是“复活节”彩蛋,而是“鸡兔同笼问题”……

如果你想到的是“鸡兔同笼”,那么恭喜你,至少你不是一个人……(表示看到兔子从蛋里钻出来的时候,竟然完全没有怀疑 )。

鸡兔同笼问题

鸡兔同笼-起源

“鸡兔同笼问题”是我国古算书《孙子算经》中著名的数学问题,其内容是:“今有雉(鸡)兔同笼,上有三十五头,下有九十四足。问雉兔各几何。”

前端实现鸡兔同笼的计算功能

功能特效:

如果你具有一定JS基础,不妨尝试书写一下或想一想,再看“功能实现”,涉及到的小细节知识可不少,特别是没有内容的对象({})的检测方法。

鸡兔同笼功能的基本实现

鸡兔计算的核心公式

兔子数量 = 脚数 / 2 - 头数;

鸡数量 = 头数 - 兔子数量。

Tips:当然,如果你考虑用for循环,从1只兔子到N只兔子,一个一个尝试组合,也并非不可,但是循环匹配的方法计算效率实在是太低了,并不推荐。另外,关于公式的“推导”过程,可详见下图:

核心功能函数

function caculate(head, foot) {

    var result = {};
    var rabbit = foot / 2 - head;
    var chicken = head - rabbit;
    if (rabbit * chicken > 0 && parseInt(rabbit) == rabbit) {
        result = {
            'rabbit' : rabbit,
            'chicken' : chicken
        }
    };
    return result;
}

注意,此处增加了一个if判断。

rabbit * chicken > 0 用于保证至少有一只鸡、一只兔(能够防止负值和0的出现)

parseInt(rabbit) == rabbit 用于防止小数的产生。

无论是0、负数、还是小数,针对这个实例都是不合法的,因此需要进行控制。在有合法结果时返回一个对象,而在没有合法结果时返回一个空的对象 - {}

对象的检测

如何检测一个没有内容的对象呢?这个问题反而成为了解决“鸡兔同笼”功能需求的关键。

码匠:如何判断一个对象是没有内容的?

码匠好友:判断{}是否等于{}?

码匠:{} == {} 是不可能成立的,虽然两个对象都是没有内容的,但是这是两个对象。所以该方法不可行……

码匠好友:让{}与null相比较?{}不是没有内容吗?

码匠:虽然{}对象当中没有内容,但是它并不等于null。所以该方法也是不可行的。

码匠好友:进行长度检测?

码匠:length属性可用于数组,但不能用于对象。

码匠好友:使用for-in循环进行枚举总可以了吧!(详见如下检测案例1)

码匠:枚举的确能够实现,但是太过繁琐,可以其他一些方法进行实现。(详见如下检测案例2、3)

检测案例1 - 利用for-in循环枚举

var obj = {};
function checkObj(obj) {
    for(var i in obj) {
        if(obj.hasOwnProperty(i)){
            return false; // 不为空对象

        }
    }

    return true; // 空对象,返回true

}
checkObj(obj);

相关说明:使用for-in循环进行枚举,对于没有内容的空对象({}),i值并不会被赋值,for-in中的内容也不会执行。

对于hasOwnProperty的检测,主要是让方法检测该属性是否是自身属性,而非原型链上(继承而来)的属性。

类似方法:使用Object.keys(obj);

Object.keys(obj); 该方法类似于枚举,但是,是直接调用Object的keys方法,方法的返回值为 —— 所有可枚举属性的字符串数组。如果当前对象为空({}),则返回一个空数组。

var obj = {};
var checkResult = Object.keys(obj);
console.log(checkResult.length);

检测案例2 - 利用JSON.stringify方法

var obj = {};
console.log(JSON.stringify(obj) == '{}')

JSON.stringify()方法,用于将JSON对象转换为字符串,当将对象转换为字符串之后,自然就可以和另一个字符串相比较了~~~

在本案例中,HTML5学堂(码匠)选用的是该种方法。

第3方法:getOwnPropertyNames

Object.getOwnPropertyNames()方法,返回对象中,除了原型属性之外的所有属性(包括不可枚举属性),返回的内容为数组,如果该对象没有属性,则返回空数组。

由于该方法返回值为一个数组,因此可以通过length属性,进行判断,如果length长度为0,则代表该对象为空。

var obj = {};
var checkResult = Object.getOwnPropertyNames(obj);
console.log(checkResult.length);

完整功能代码

结构代码

行为代码

涉及到的细节知识

字符串转换为数字

通过input获取到的值,类型为字符串,需要优先转换为数字,再进行操作,在本案例中HTML5学堂(码匠)选用的是Number方法。

NaN的基本检测

当用户在input中输入非数字或不合法数字时,会通过上面的Number方法转换为NaN。

当出现NaN时,则需要给用户给予反馈,而不是继续进行运算,因此需要进行NaN进行检测。

NaN检测的方法很简单,让其与自身相比较,如果自己和自己不相等,那么,该值为NaN

整数检测

在鸡兔同笼计算当中,有可能用户输入的内容是合法数字,也是合法整数,但是有可能在运算之后变成小数。这种情况,是由于用户输入了不成立的数字组合。例如:头3只,脚7只。

对于此类问题,需要借助数字取整来检测,此处HTML5学堂(码匠)使用的是parseInt方法,针对兔子的数字取整,然后再跟原始的兔子数字比较,如果相同,则原始数字为整数。

没有内容的对象检测

在上面已经进行了详细讲解,在此罗列一下检测没有内容的对象的方法:

● JSON.stringify(obj);

● Object.keys(obj);

● Object.getOwnPropertyNames(obj);

查看效果实例:https://codepen.io/majiang/pen/oWoGmz