记录JavaScript中的特殊知识点
理解JavaScript的浮点数
我们知道JavaScript的数值型类型只有一种,即number,不像Java有int/float.
实际上,JavaScript所有数字都是双精度浮点数.这是因为IEEE754标准制定的64位编码数字doubles.双精度浮点数表示范围 -2^53 ~ 2^53 .
浮点数运算的精度陷阱问题.
console.log(0.1 + 0.2)// 0.30000000000000004
JavaScript的整数只是双精度浮点数的一个子集.
隐式的强制转换
由于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()); // 40
JavaScript变量声明提升
其实这么理解就可以,变量的声明是两部分,分为变量的声明和变量的赋值.
而变量的提升就是把变量的声明(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不存在.