JavaScript基础入门教程(二)
说明
前一篇博客介绍了js以及一些关于js基本类型的简单知识,本篇博客将详细介绍js的基础类型,捎带介绍对象类型,更详细的对象类型的说明将后续再讲。
js中类型的说明
js中的类型分为基本类型和对象类型,其中基本类型包括:①数字、②字符串、③布尔值。此外还有两个原始值null和undefined。其中对象包括数组对象、函数对象和普通对象,普通对象是“命名值”的无序集合,而数组对象是带编号的值的有序集合。JavaScript核心还定义了三种有用的类:日期(Data)类、正则(RegExp)类、错误(Error)类。
数字
和常见的其它编程语言不同,js不区分整数和浮点数,js中所有的数值均用浮点数值表示。
整型直接量
在js中一个数字序列默认是十进制的整数,同时支持使用"0x"或"0X"开头的十六进制,值得注意的是虽然有些JavaScript解释器支持0开头的八进制表示形式,但是ECMAScript标准并不支持,所以尽量不要使用八进制表示形式,以免出现移植上的问题。
浮点型直接量
浮点型直接量的表示形式为:[digits][.digits][(E|e)[(+|-)]digits],例如①3.14、②6.02e23、③.22e-23 //0.22x10-23
js中的算术运算
js不仅支持常见的加(+)减(-)乘(*)除(/)和求余(%),还支持更复杂的运算,不过需要Math对象的支持:
js语句 | 作用 |
Math.pow(2,53) | 求2的53次幂 |
Math.round(0.6) | 四舍五入,结果为1.0 |
Math.max(x,y,z) | 求最大值 |
Math.PI | 返回圆周率π的值 |
js的算术运算会出现上溢和下溢,这与其它语言稍有区别,上溢的结果为Infinity或-Infinity,下溢的结果为0或-0,一般0和-0没什么区别(0===-0结果为true),但有时候还是会有不同,比如1/0结果为Infinity,而1/-0结果为-Infinity。此外还有一个结果就是NaN(Not a Number),当出现结果不是数字或者无法将其转化为数字时用NaN表示,比如负数开方、零除以零、无穷大除以无穷大等操作。
全局函数isNaN()和全局函数isFinity()可以用于判断数值的类型,当一个数是NaN时isNaN()函数返回true,当一个数不是NaN、Infinity或-Infinity时isFinity()返回true。
二进制浮点数的四舍五入错误
看下面的代码:
1 var x = .3 - .2; 2 var y = .2 - .1; 3 x == y //false 4 x == .1 //false 5 y == .1 //true
造成这种结果的原因是因为二进制浮点数的表示是近似表示,值得注意的是这种问题不仅在js中会出现,在其它所有利用浮点数计算的语言中都会存在。为了更好的解决这种问题可以将自己要算的数同时扩大一个倍数,看下面的代码:
1 var x = 3 - 2; 2 var y = 2 - 1; 3 x == y; //true
日期和时间
Date是js的语言核心的一部分,这里简单介绍Date的一些简单用法,更详细的介绍将在后续的博客中介绍。
1 var now = new Date(); //获取当前时间 2 var then = new Date(2011,0,1); //2011年1月1号 3 var later = new Date(2011,0,1,17,10,30) //2011年1月1号17时10分30秒 4 var elapsed = now - then; //结果为时间间隔的毫秒数 5 later.getFullYear(); //2011 6 later.getMonth(); //0:月份计数从0开始 7 later.getDate(); //1:每月的日期计数从1开始 8 later.getDay(); //6:0代表星期日,6代表星期六
文本
说起字符串,就需要谈到编码方式了,js采用UTF-16的Unicode编码,这样以来处于“基本多语种平面”的字符都是两个字节,而处于“辅助多语种平面”的字符是四个字节。这意味在js中长度为2的字符串可能有两个字符,也可能只有一个字符。
1 var p = "π"; 2 var e = "𝑒";//"\ud835\udc52" 3 p.length //1 4 e.length //2
需要注意一点,js中定义的各种函数操作全部是针对“基本多语种平面"的,所以在处理字符串时需要当心。
字符串直接量
字符串直接量可以使用单引号或双引号括起来,在ECMAScript3中,字符串直接量必须写在一行中,而在ECMAScript5中,字符串直接量可以拆分成数行,但是每一行的结尾必须是反斜杠(\)。
1 "Wouldn't you prefer D'Reilly's book?" 2 "one \ 3 long \ 4 line" //ECMAScript5
因为js和html都支持单引号和双引号来括起内容,所以一般分别用不同的引号来括起各自的内容:
1 <bytton onclick="alert('hello world')">click me</button>
字符串的使用
和java一样,js支持字符串使用加号进行拼接,字符串"hello, "+"world"等价于"hello, world"。要确定一个字符串的长度可以使用其length属性,此外js的字符串还有许多方法可供调用:
1 var s="hello, world"; 2 var len=s.length; 3 s.charAt(0) //h:第一个字符 4 s.charAt(s.length-1) //d:最后一个字符 5 s.substring(1,4) //ell:第2-4个字符 6 s.slice(1,4) //ell:同上 7 s.slice(-3) //rld:最后三个字符 8 s.indexOf("l") //2:字符l第一次出现的位置 9 s.lastIndexOf("l") //10:字符l最后出现的位置 10 s.indexOf("l",3) //3:在位置3及其之后,字符l第一次出现的位置 11 s.split(", ") //["hello","world"]:根据", "将字符串分割成子串存在数组中。 12 s.replace("h","H") //"Hello, world":替换全文中所有的h为H 13 s.toUpperCase() //"HELLO, WORLD
此外字符串的引用还有下标法,也就是说s.charAt(0)等价于s[0]。和java一样,JavaScript 的字符串是不可变的(immutable),String 类定义的方法都不能改变字符串的内容。像 String.toUpperCase() 这样的方法,返回的是全新的字符串,而不是修改原始字符串。
布尔值
在条件判断时以下值会转化为false,其它所有情况将转化为true,包括数组、函数、对象等。值得注意的是,虽然0将转化为false,但是"0"还是转化为true。
1 undefined 2 null 3 0 4 -0 5 NaN 6 "" //空字符串
null和undefined
尽管null和undefined不尽相同,但是他们也经常可以互换。比如null==undefined的结果就为true(可以使用===严格等于判断null和undefined不等)。一般来说null和undefined的区别就是null是存在但空缺值,而undefined是不存在。比如某个变量被定义了,但是没值一般是null,但是如果是某个对象根本不存在length这个属性,而我们强行使用他的length属性就会返回undefined。
包装对象
学到现在你可能好奇过为什么js中的基本数据类型也有属性,比如下面的代码,虽然s是字符串类型,但它依然有属性。学过java的部分同学可能纠结string不应该是Object类型的一种吗?这里的回答是“不”,在js中string是一种独立的基本类型,而String才是Object类型的一种。
1 var s="hello, world" 2 var world=s.substring(s.indexOf("w"), s.length);
之所以会产生上面的效果,究其根本就是js的包装类型造成的。js解释器会在变量的每次使用时将一个基本类型转化为一个临时的对应的包装类的类型,比如上面的s在使用它的length属性时,js解释器会自动执行类似temp=new String(s); temp.length;的操作来替代刚才那句话。同字符串一样,数字和布尔值也都有对应的包装类类型的构造函数,分别是Number()和Boolean()。null和undefined都没有包装类,访问它们属性都将报错。
在判等时,==运算符会判定值相同的基本类型和其对应的包装类型相等,而===则判定不等。
可变对象的引用
对象和原始值不同,首先它们时可变的——它们的值是可修改的:
1 var o={x:1}; //定义一个对象 2 o.x=2; //通过修改对象属性值来更改对象 3 o.y=3; //再次更改这个对象,给它增加一个新属性 4 5 var a=[1,2,3]; //数组也是可以修改的 6 a[0]=0; //更改数组的一个元素 7 a[3]=4; //给数组新增一个元素
数组和对象类型的比较是引用比较,这个和java语言相似,两个对象即使类型相同并且属性值也相同,它们还是不等。只有两个引用指向同一个对象,这两个引用才相等。
类型转换
由于js的弱类型,所以js解释器本身会自动进行大量的隐式转换,如果期望一个布尔值,js会把给定的值转化为布尔值,转化规则见上面,同理如果期望字符串,js会自动把给定的值转化为字符串类型,如果期望数字,它也会自动把值转化为数字(如果转化结果没有意义将得到NaN)。
显示类型转换
做显示类型转换最简单的方式就是使用Boolean()、Number()、String()或Object()函数,这些函数在不通过new创建对象时会作为类型转换函数:
1 Number("3") //3 2 String(false) //"false" 3 Boolean([]) //true 4 Object(3) //new Number(3)
Number类定义的toString()方法可以接收表示基础的可选参数:
1 var n=17; 2 var binary_string = n.toString(2); //转换为"10001" 3 var octal_string = n.toString(8); //转换为"21" 4 var hex_string = n.toString(16); //转换为"11"
此外还有用于处理浮点数精度相关的函数,toFixed(n)表示指定小数点后的位数为n,toExponential(n)表示用科学计数法表示且小数点后位数为n,toPrecision(n)表示有效数字为n,当整数位数比n大时用科学记数法表示。细节部分就是toExponential转换后整数部分只有一位数,所有这些转换都满足四舍五入原则。
var n=123456.789; n.toFixed(0); //"123457" n.toFixed(2); //"123456.79" n.toFixed(5); //"123456.78900" n.toExponential(1); //"1.2e+5" n.toExponential(3); //"1.235e+5" n.toPrecision(4); //"1.235e+5" n.toPrecision(7); //"123456.8" n.toPrecision(10); //"123456.7890"
前面讲的时由数字转字符串,接下来谈一下字符串转化为数字的操作,主要是利用parseInt()和parseFloat()这两个全局函数。
1 parseInt("3 blind mice") //3 2 parseFloat(" 3.14 meters") //3.14 3 parseInt("-12.34") //-12 4 parseInt("-0xFF") //-255 5 parseInt(".1") //NaN 6 parseInt("0.1") //0 7 parseFloat(".1") //0.1 8 parseFloat("$72.47") //NaN 9 10 parseInt("11",2) //3 11 parseInt("ff",16) //255 12 parseInt("zz",36) //1295 13 parseInt("77",8) //63
看上面的例子可以简单的了解以下parseInt和parseFloat这两个函数的基本用法,parseInt函数解析的字符串第一个可见字符(去掉空格)必须是数值,这也就是第5行代码错误的原因。相比而言parseFloat函数的第一个可见字符增加了小数点,见第7行代码。不管是parseInt还是parseFloat函数,其数值后的字母开始的内容都将被忽略,见第1、2行代码。默认情况下parseInt还支持使用0x或0X开头的十六进制整数表示,见第4行代码。此外parseInt还支持两个参数的调用,其第二个参数是指定解析的基数(支持2-36),比如第13行代码parseInt("77",8)表示用八进制的方式来读取”77“这个字符串。
隐式类型转换
接下来的关于隐式类型转换的东西,个人觉得这篇博客比《JavaScript权威指南》讲的要好一点。
下面讲一下我自己对隐式类型转换的理解。
参考了:https://blog.csdn.net/itcast_cn/article/details/82887895
首先明确js中发生隐式类型转换的几种基本类型:数字类型、字符串类型、布尔类型、对象类型。
- 目标是字符串类型:+(作为字符串连接符,即该运算符两边至少有一边出现字符串)
- 目标是布尔类型:!(逻辑取反)
- 目标是数字类型:++、--、+、-、*、/、<等运算符
1 if([] == 0) 2 console.log(!![]) // 输出 true
上述代码会输出true,首先逻辑判断里面是==运算符,但是运算符两边类型不同,所以要进行隐式类型转换,这里既不是字符串连接符也不是逻辑取反运算符,所以目标是数字类型,即将==运算符两边都转换为数字类型。空数组转化为数字类型的结果恰好是0,于是if条件被满足。console.log里的!运算符会对空数组进行隐式类型转换,目标是布尔类型,结果是true。