JavaScript学习笔记3:计算器案例代码分析

1、今天尝试完成昨天遗留的计算器作业,没想到进入太多的坑。

  • 关于document.getElementById(‘ID’).value方法需要注意的情况
  • onclick、onchange等事件的触发机制
  • 浮点数的运算精确度

下面通过代码片段来慢慢解释:

关于document.getElementById('ID').value

//html
<div id="caculator">
   <input type="text" value="123456" id="test" />
</div>

//js代码1
console.log(test);//输出<input type="text" value="123456" id="test" />

🔺变量test虽然没有被定义,但是test是html元素的ID,在这种情况下js默认输出该ID所包含的元素块(见图片1);如果此时使用alert(test)或.innerHTML来进行输出其value的话,输出的字符为:[object HTMLInputElement]或者类似;如果页面中没有test这个Id的HTML元素的话,控制台能看到报错信息:Uncaught ReferenceError: test is not defined.

//js代码2
var test = document.getElementById('test').value;
function charTest() {
    console.log(test);
}
charTest();//输出123456
🔺变量test与Html元素Id相同,但是这里被重新声明过了,用来指代该元素的value,所以才能输出数值字符串;
🔺算然声明定义了test变量,但是该变量依托HTML页面中ID为test的元素块的内容;如果该ID被删除或者改写,控制台中仍然会报错:Uncaught TypeError: Cannot read property 'value' of null。这应该是value方法的缘故吧。
 
图片1:页面HTML标签中的ID,若没有单独重新声明,该ID指代该ID下的整个HTML块
下面贴出整个计算器页面布局的HTML部分:
<div id="caculator">
    <input id="num1" type="number" value="0" placeholder="请输入第一个数字" />
    <br>
    <input id="num2" type="number" value="0" placeholder="请输入第二个数字" />
    <br>
    <button id="jia" type="button">➕</button>
    <button id="jian" type="button">➖</button>
    <button id="cheng" type="button">✖</button>
    <button id="chu" type="button">➗</button>
    <br>
    <p>计算结果为:<span id="result"></span></p>
</div>
图2:以上HTML代码获得计算器显示效果(代码不包含CSS样式)
//下面贴出该计算器可运行的js代码块
var data1 = data2 = 0;
document.getElementById('num1').onchange = function() {
    data1 = document.getElementById('num1').value * 1;
};

document.getElementById('num2').onchange = function() {
    data2 = document.getElementById('num2').value * 1;
};

document.getElementById('jia').onclick = function() {
    calculator('+');
}
document.getElementById('jian').onclick = function() {
    calculator('-');
}
document.getElementById('cheng').onclick = function() {
    calculator('*');
}
document.getElementById('chu').onclick = function() {
    calculator('/');
}

function calculator(method) {
    console.log(data1, data2);
    switch (method) {
        case '+':
            document.getElementById('result').innerHTML = parseFloat((data1 + data2).toFixed(100));
            break;
        case '-':
            document.getElementById('result').innerHTML = parseFloat((data1 - data2).toFixed(100));
            break;
        case '*':
            document.getElementById('result').innerHTML = parseFloat((data1 * data2).toFixed(100));
            break;
        case '/':
            document.getElementById('result').innerHTML = parseFloat((data1 / data2).toFixed(100));
            break;
    }
}

一个需要注意的问题是,这里的onchange和onclick不是直接写在HTML标签元素上的,也就是没采用下面这样的样式:

<input type="number" onclick="alert('Hello World!');" />

而是使用了类似下面的样式:

document.getElementById('ID').onchange = function(){}

这里面onchange\onclick事件写法不同会产生不同的结果

    <input id="btn" type="button" value="点我弹窗" onclick="alert('hello world')">

🔺上边的写法是单独在元素中绑定事件,这样写是有效的;但是就目前来说,为了SEO效果一般不推荐这么写了

▼如果通过引入的方式来写,则需要写成如下样式,并且在上面的HTML标签里面删除已经绑定的onclick事件,否则因为同时执行两个事件,JS会不做任何操作,即使两个事件是完全相同的。

    <script>
        document.getElementById("btn").onclick = function() {
            alert('hello world');
        }
    </script>
🔺但是有一个疑问上面的为何不能直接写成下面的样式:
document.getElementById("btn").onclick = alert('hello world');
//当使用上面的写法时,alert在HTML文档打开之后就立即执行了,而不是依托于onclick事件,难道这个=号右边的alert方法被当成了赋值?而.onclick被当成了一个对象属性?下面再写一个例子来验证:

var e = '';
var getSum = function(e) {
        alert('你的名字是:' + e );
    } //在使用function(){}包裹之后 alert并没有运行;此时getSum的类型是function,!!!!!是需要等待被执行的!!!!!!

var getSum = alert('我来进行求和运算');//解除function(){}包裹之后,alert在文档载入后就立即运行了。此时getSum的类型是undefined;有没有他无所谓;alert本身不是一个值,与prompt不同,prompt可以进行赋值,与之对应的对象类型是string;

可能我需要了解function这个关键字的含义和用法?事件绑定在标签元素上和作为引用的写法有所不同。上面的例子如果是下面的写法,则能够与事件绑定,达成要求的效果。

<input id="btn" type="button" value="点我弹窗" onclick="getSum('张三')">

以上总结,promptalertconsole等输入输出方法可以直接运行,前面也可以加变量,但是除了prompt之外,另外两个输出的方法加变量似乎没有什么意义。onclick事件的使用方法见 this page,引用的方法如下2种:

object.onclick = function(){ 
     // my script;
}
或者:
object.addEventListener('click',myScript);//IE8及更早不支持

最后是关于浮点运算的,之前看到的在加法运算时乘以10再除以10的方案局限性太明显,只能用在小数点后一位吧?现在可以用tofix()来解决这个问题了,使用的方式参照parseFloat((运算表达式).toFixed(10))10代表小数点后取的位数。