JavaScript的类型、值和变量
计算机程序的运行需要对值进行操作,在编程语言中,能够表示并操作的值得类型称为数据类型。变量用来将值存储起来,变量是值得符号名称。
一、数据类型
JavaScript的数据类型可以分为两类,原生类型和对象类型,JavaScript的原始类型包括数字、字符串和布尔值,JavaScript还有两个特殊的原始值null(空)和undefined(未定义),它们不是数字、字符串和布尔值。对象类型包含普通对象、数组、函数、日期、正则、错误对象。
JavaScript的类型也可以按有无方法分,除了null和undefined,其他的类型都是拥有方法的值,字符串、数字、布尔值在使用方法时,会临时转化为对应的对象。
JavaScript的类型也可以可变类型和不可变类型,只有对象和数组属于可变类型,其他的都是不可变类型,包括字符串。
二、JavaScript的内存管理机制
JavaScript解释器有自己的内存管理机制,可以自动对内存进行垃圾回收。这意味着程序员可以按需创建对象,程序员则不必担心这些对象的销毁和内存回收,当不再有任何引用指向一个对象,解释器就会知道这个对象没用了 ,然后就自动回收它所占的内存资源。
三、数值
a、JavaScript中数值有整型和浮点型
整型可以用十进制和十六进制(0xff).
浮点型可以包含小数点,可以采用传统写法,还可以使用指数计数法。
3.14
6.02e23 //6.02x1023
6.02E-23 //6.02x10-23
b、JavaScript中的算术运算
JavaScript运算符包括+、-、*、/、%(求余).除了基本的运算符外,Javascript还支持更复杂运算。这些运算和Math对象的属性和方法有关。
Math对象的属性
Math对象的方法
例子:
Math.round(Math.random()*10) //返回0到10(包含0和10)的整数
溢出:当数值超出了JavaScript所能表示的数字上限(溢出),结果为一个无穷大值。表示为Infinity。
当负数超出了JavaScript所能表示的负数范围,结果为负无穷大。表示为-Infinity。
基于无穷大的加减乘除让是无穷大,保留其原来的符号。
下溢:当运算结果无限接近0且比JavaScript所能表示的最小值还小时发生下溢。这种情况下JavaScript返回0。正数下溢返回0;负数下溢返 回-0;0和-0几乎没有区别(除了作为除数)。
1 var a=0;
2 var b=-0;
3 console.log(a===b); //true
4 console.log(1/a===1/b) //false
被0整除并不会报错。
1 var a=1;
2 console.log(a/0); //Infinity
3 console.log(a/-0); //-Infinity
4console.log(0/0) //NaN
NaN(not -a-number)://表示不是一个数字
0/0、无穷大除无穷大、给负数开偶次方、算术运算符的操作数不是一个数字或者无法转化成数字(+运算符特殊)。
1 console.log(0/0); //NaN
2 console.log(Infinity/Infinity); //NaN
3 console.log(Math.sqrt(-3)) //NaN
4 console.log('a2'-3); //NaN
Infinity和NaN是JavaScript中定义的全局变量。
NaN和任何值都不相等,包括自身。所以判断一个值x是不是NaN,应使用x!=x。
isNaN是一个全局函数。可以用来判断一个数字是不是NaN,如何一个是NaN或者不能转换成一个数字,返回true.
1 console.log(isNaN([])); //false
2 console.log(isNaN('3')) //fase
3 console.log(isNaN('ab')) //true
isFinity()也是一个全局函数。当参数是NaN(转化成数字),-Infinity,Infinity的时候,返回false.其他时候都是返回true.
1 console.log(isFinite(Infinity)); //false
2 console.log(isFinite(NaN)) //false
3 console.log(isFinite('ab')) //false
四、字符串
字符串一个一组不可变字符组成的序列,字符串的字符索引从0开始,字符串的长度是其所包含的字符的个数,空字符的长度为0.
字符串直接量要用单引号或者双引号括起来,字符换换行用反斜线\连接。
‘’\'在字符串中有着特殊用途,'\'+字符会改变字符原来的意思。'\n'代表换行,这类字符称作转义字符。
五、布尔值
布尔值指代真或假,只有两个值true和false。JavaScript中比较运算通常返回的都是布尔值。
a=1;b=2;
a==b;//返回false
六、null和undefined
null是JavaScript中的关键字。常用来表示空值。typeof null会返回"object".实际上null是它自有类型的唯一值。他表示数字、字符串、对象是无值的。
undefined是JavaScript中的全局变量,表示变量的值没有初始化。typeof undefined返回"undefined"。是它自有类型的唯一成员。
1 console.log(typeof null); //object
2 console.log(typeof undefined); //undefined
==运算符认为他两个是相等。
七、全局对象
全局对象的属性是全局定义的符号,JavaScript可以直接使用。当JavaScript解释器启动时,他会创建一个新的全局对象,并给他一组定义的初始属性。
全局属性:undefined、Infinity、NaN等
全局函数:isNaN()、eval()等
构造函数:Date()、Array()等
全局对象:Math、JSON
全局对象的初始属性不是保留字,但是应该当做保留字对待。
在最顶级代码中,可以使用this关键字引用全局对象。全局对象定义了JavaScript中的所有的预定义全局值。这个特殊对象同时包含了程序定义的全局值(用户自定义的全局变量)。
八、包装对象
JavaScript中的数字、字符串、布尔值也可以调用方法。这些原始值在调用方法之前会通过对应的构造函数转化成对象,调用对象的方法(属性),对象会自动销毁。
1 var s="s";
2 s.len=4;//给它设置属性
3 console.log(s.len);//undefined
null和undefined没有包装对象。访问它们的属性会报错。
==认为包装对象是相等的,而===认为他们是不等。
typeof可以看出其中的差别。
1 var s="s";
2 var S=new String(s)
3 console.log(typeof s);//"string"
4 console.log(typeof S);//"object"
九、不可变的原始值和可变的对象引用
原始值是不可变的。通过字符串的方法修改字符串返回一个新的字符串,而字符串的原始值并没改变。
1 var s="sdasd";
2 console.log(s.toUpperCase());//"SDASD"
3 console.log(s);//"sdasd"
原始值得比较是值得比较。例如字符串只要长度相等,对应位置的字符相等,则认为它们是相等。
对象和原始值不同,对象的值是可变的。
1 var obj={
2 a:1,
3 b:2
4 }
5 obj.a=3;
6 console.log(obj.a); //3
对象的比较不能通过值来比较,即使两个对象同样的值属性且属性值相等。它们也是不相等。
变量存储的是对象的引用值,即对象在堆中的地址。只有引用值相等。才能认为两个对象是相等。
十、类型转换
a.隐式类型转化
JavaScript中的取值类型非常灵活,可以根据需要自动转化类型。
对象转换成布尔值:所有的对象都会转换成true;new Boolean(false)对象也会转换成true.
对象转换成数字和对象转换成字符串:这里提到到转换方法只适合于本地对象(宿主对象(Web浏览器定义的对象)有自己的转换规则)。所有的对象都继承了两个转化方法。
第一个是toString()方法:默认的toString()方法用来返回对象的类型。
1 var obj={
2 a:1,
3 b:2
4 }
5 console.log(obj.toString()); //[object object]
日期对象、数组、函数、正则对象的toString()方法。
1 console.log([1,2,3].toString()); //1,2,3
2 console.log(new Date().toString()) //Wed Mar 07 2018 02:01:18 GMT+0800 (中国标准时间)
3 console.log(function(){return 0;}.toString()) //function (){return 0;}
4 console.log(/\d+/i.toString()) // /\d+/i
第二个方法时valueOf().如果对象存在原始值。则这个方法返回原始值,大多数对象无法还原成原始值,valueOf()简单返回对象本身。数组、函数、正则对象的valueOf()方法返回对象本身。而日期对象的valueOf()返回的是1970.1.1到现在的毫秒数。
1 console.log(new Date().valueOf()) //1520359837257
JavaScript中的对象转换成字符串:--如果对象有toString()方法,调用这个方法返回一个原始值,再把原始值转换成字符串。
--如果对象没有toString()方法,或者这个方法返回的不是一个原始值,则调用valueOf(),调用这个方法返回一个原始值,再把原始值转换成字符串。
--如果不能通过上述的两个方获得原始值,则抛出一个类型错误。
JavaScript对象转换成数字:和转发成字符串的方法类似,不过先调用valueOf()方法获得原始值,转换成数字。
+、==、!=、关系运算符(>、<)中对象到原始值的转换:先调用valueOf(),在调用toString()。得到的原始值直接使用。
+、==操作日期对象时转化成数字、字符串:先调用toString(),在调用valueOf(),得到原始值直接使用。
1 var now=new Date();
2 console.log(now==now.toString());//true 先调用toString()
3 console.log(now+1) //Wed Mar 07 2018 02:37:30 GMT+0800 (中国标准时间)1 先调用toString()
4 console.log(now>now-1) //true 先调用valueOf()
b、显示类型转换
转换成数字:Number()函数、ParseInt()、ParseFloat()
Number()只能基于10进制进行转换,不能出现非法的尾随字符:
ParseInt()用于整型:可以忽略前导空格、尽可能多的解析更多数值,忽略后面的内容,不能转换返回NaN
ParseFloat()整型和浮点型 可以忽略前导空格、尽可能多的解析更多数值,忽略后面的内容,不能转换返回NaN
parseInt可以接受第二个参数,这个参数指定数字的基数(2~36)。
转换成字符串:String()、toString()
String()函数会把null、undefined转换成空对象,而toString()方法会报错。
toString()在用于数字到字符串的转换时,可以在参数中输入数的基数,表示数字是几进制的。
1 var n=12;
2 console.log(n.toString(16));//c
toFixed()、toExponential()、toPrecision()也可以用于数字到字符串的转换;
toFixed(arg):参数用来指定小数的位数
toExponential(arg):使用指数计数法表示数字,小数点前只有一位,参数指定了小数点后的位数
toPrecision(arg):arg指定有效数字的位数,如果有效数字的位数少于整数部分的位数,则使用指数表示。
以上的三个方法会进行四舍五入和补0操作。
1 var a=123456.789
2 console.log(a.toFixed(0)) //"123457"
3 console.log(a.toFixed(1)) //"123456.8"
4 console.log(a.toFixed(5)) //"123456.78900"
5 console.log(a.toExponential(2)) //"1.23E5"
6 console.log(a.toExponential(3)) //"1.235E5"
7 console.log(a.toPrecision(3)) //"1.23e5"
8 console.log(a.toPrecision(7)) //"123456.8"
转换成对象:Object()
转换成布尔值:Boolean()
十一、变量声明
a、用var关键字声明变量:
var x,y; var x=1,y=2;
声明的变量没有初始化之前的值是undefined.
可以使用声明一个变量多次,但是不能使用未声明的变量。不使用var关键字声明的变量是全局变量,无论位置。不用var声明的变量可以用delete 删除。
b、全局变量和局部变量
全局变量拥有全局作用,局部变量只在函数内可见,函数体局部变量的优先级高于全局变量。
c、变量声明提前
在函数中变量的声明前就可以用,变量的声明就好像放在函数的最前面一样。
1 (function(){ 2 console.log(a);//undefined 3 var a=0; 4 console.log(a);//0 5 })();
十二、作用域链
JavaScript中规定全局变量是全局对象的属性,可以通过this关键字引用全局变量。而局部变量是与函数调用相关的某个对象的属性,JavaScript中没有办法引用该对象。作用域链是一个链表,上面存放了当前位置代码可访问的变量的保存对象。JavaScript需要访问某个变量时,它会在作用域链的对象上查找是否有该属性,直到找到该属性,否则会报错。
函数在定义的时候保存一个作用域链,当函数调用的时候,创建一个对象用来保存函数内部的局部变量,然后把对象添加到作用域链上,同时创建一个新的更长的函数调用链。当函数有嵌套函数时,函数每次调用时内部函数的作用域链都是不同的。