理解JavaScript的浮点数
我们知道JavaScript的数值型类型只有一种,即number,不像Java有int/float. 实际上,JavaScript所有数字都是双精度浮点数.这是因为IEEE754标准制定的64位编码数字doubles.双精度浮点数表示范围 -2^53 ~ 2^53 .
浮点数运算的精度陷阱问题.
console.log(0.1 + 0.2)// 0.30000000000000004JavaScript的整数只是双精度浮点数的一个子集.
隐式的强制转换
由于JavaScript的自身特性,在处理JavaScript表达式时候,经常会有很多隐式的类型转换,一不注意就很容易出错.出错了还不利于调试,因为隐式强转不容易被发现.
多半涉及如下的强制转换规则:
布尔值转为数值字符串转为数值其他数据类型转为布尔值区分+运算符的使用情况 JavaScript里面的7个假值 false , 0 , '' ,undefined , -0 , NaN , undefined在调用函数时候,我们可以通过对参数进行处理达到一个筛选的目的.
function(x,y){ // x,y 为假值的情况 if(!x && !y){ } // x,y 为undefined的情况 if(typeof x === 'undefined'){ } if(typeof y === 'undefined'){ } }基本数据类型的包装函数
这个指的是String,Number,Boolean的包装函数.可以把基本数据类型封装为对象.使其具备一些对象的行为.
var str1 = 'hello'; var str2 = 'hello'; console.log(str1 == str2); // true var str3 = new String('hello'); var str4 = new String('hello'); console.log(str3 == str4);// false console.log(str3[0]); // 'h' console.log(str1[0]); // 'h'我们需要理解的是:
你获取或者设置一个基本数据类型值的时候,其实会隐式创建了一个对应的封装对象.对象的toString()与valueOf()
对象可以通过toString()返回一个字符串. 对象可以通过valueOf()返回一个数值.
console.log( '1.00' == {valueOf: function(){return true}} ); // true console.log('hello' + {toString: function(){return 'worid'}}); // helloworid如果一个对象同时具备valueOf()与toString(),当碰到运算符’+’时候,JavaScript选择valueOf()方法
var obj = { valueOf: function(){ return 10; }, toString: function(){ return 'world' } }; console.log( 'hello' + obj ); // hello10理解’==’ 相等运算符 与 ‘===’ 严格相等运算符
如果比较的两个参数是相同的数据类型,那么使用”==”与”===”没有什么区别. 推荐使用”===”,因为你知道比较过程中不涉及类型的转换.
重点学习下”==”的转换规则:
JavaScript对于分号的插入规则
有些人通过JavaScript的自动分号插入技术,写JavaScript习惯不写分号,这是有一定弊端的,如果你不了解它的分号插入规则.
// 规则 - JavaScript会在一行,一个代码块,一段程序结束的地方插入分号. - JavaScript在遇到不能解析的输入标记时候插入分号 - 以(,[,+,-,/,开头的语句前面不可以省略分号 - 在return , break ,throw , continue , ++ ,-- 之前绝不可以换行 - 在for循环时候,不要在循环头部/空语句的分隔符被JavaScript推导出分号掌握闭包
理解闭包只需要掌握下面三个规则:
在JavaScript里面,我们是可以引用除当前函数作用域以外定义的变量. function fx(){ var str = 'hello'; function say(name){ return str + name; } return say('kobe'); } var str1 = fx(); console.log(str1); // hellokobe // 可见在say()函数里面.是可以访问到外部str变量的 即便外部函数执行完.当前函数仍然可以访问到外部函数定义的变量 function fx(){ var str = 'hello'; function say(name){ return str + name; } return say; } var repeat = fx(); console.log( repeat('kobe') ); // hellokobe // 我们都知道repeat其实就是指的是say函数,按理说fx()执行完,str变量应该被销毁,但是它仍然被say()函数引用了,因此并不会被回收. 上条规则说了,闭包的存在,可以存储外部函数变量的引用,因此它是可以改变外部变量的值 function fx(){ var flag = 10; return { getVal: function(){ return flag }, setVal: function(newVal){ flag = newVal; }, typeCheck: function(){ return typeof flag; } } }; var obj = fx(); console.log( obj.typeCheck() ); // number console.log( obj.getVal() ); // 10 obj.setVal(40); console.log(obj.getVal()); // 40JavaScript变量声明提升
其实这么理解就可以,变量的声明是两部分,分为变量的声明和变量的赋值. 而变量的提升就是把变量的声明(var 变量名)这部分提升到最近的函数作用域顶部,赋值的那部分依然在原先的位置不动,等待JavaScript从上往下解析到该位置再执行赋值。
另外对变量进行重复声明,会被视为同一个变量.JavaScript不存在块级作用域
function fx(){ return 'global' } function test(x){ debugger var res = []; if(x){ function fx(){return 'local'} res.push(fx()); } res.push(fx()) return res; } console.log( test(true)); // ['local','local'] console.log( test (false));// fx 不是一个函数 // 第一个情况,因为x = true,fx函数已经存在,并且是属于test函数内都可以访问的e,因为js不存在块级作用域 // x = false,fx不存在.