本系列教程的说明
本教程说白了可以说是我自己学习JavaScript的笔记,主要内容参考自《JavaScript权威指南》,部分内容可能来自互联网,本系列教程假设学者之前学过c或者其它的编程语言,所以一些基本for、if等语句的用法并不讲解。
javascript简介
JavaScript简称js,最初由网景(现在的Mozilla)公司创建,由于商标冲突原因,其标准版本命名为ECMAScript,但是一般人们还是叫JavaScript,只在谈标准的时候说到ECMAScript这个名字。值得注意的是JavaScript与java没有任何关系,就像雷峰塔(神话中镇压白娘子的塔)和雷锋。此外js(JavaScript)和jsp(java servlet pages)也没有关系。
js的工作分为两部分,一部分属于js语言本身的特性,而另一部需要依靠宿主环境(web浏览器)才能完成。
js的词法
字符书写
字符集方面,要求JavaScript的程序必须是用Unicode字符集编写的。代码编写是区分大小写的,值得注意的是html是不区分大小写的(xhtml区分),而这个问题在css中则稍显复杂,由于要和html结合,所以css只有在选择器选择id和class时区分大小写,其他情况都不区分大小写。
Unicode转义序列,由于我们生活中经常用到ASCII之外的字符,比如中文字符等,为了避免不必要的麻烦,JavaScript支持采用Unicode转义的方式来编码字符串。比如在js中 'café' === 'cafu00e9' 的结果是true。
在标识符定义方面,js支持使用下划线、美元符号(在jQuery中常用)、字母和数字来书写,并且数字不能开头。虽然js强大到支持使用非英语语言来书写标识符,比如 var π=3.14 ,但是从移植性考虑,并不推荐。
此外和其它语言一样,标识符绝对不能和关键字同名,js中的关键字除了包括所有java的关键字外,还包括function、typeof、var、in、debugger这些,还有arguments、eval虽然不是关键字,但是还是在严格模式下被限制而不能作为标识符。
可选的分号
在js中各语句之间可以用分号作为分隔符,类似于c语言一样,不过js中的分号是可选的,也就是有时候可以写可以不写。看下面的代码
var a a = 3 console.log(a)
js会把上面的代码解析为下面的语句执行
var a; a=3; console.log(a);
这就是js的自动添加分号的功能,如果js发现缺少分号无法正确解析代码,它就会尝试添加分号并执行,值得注意的是自动添加的分号只添加在行尾,也就是说下面的代码虽然缺少分号(3和b之间),但是js也不会自动添加,而是报错:
a=3 b=4;
虽然js拥有这么强大的功能,但是我们并不推荐这样写代码,反而有时候要防止别人这样写代码带来的麻烦,看下面的例子:
var y=x+f (a+b).toString()
看起来好像应该是两条独立的语句,事实上js会把 f(a+b) 连起来当成一个函数执行,所以上面两行只写了一条语句。因此为了防止这种错误的发生经常出现如下的代码:
... ;[x,x+1,x+2].forEach(console.log); ...
这种以(、[、/、+、-等开头的行容易引起上面的问题,故一般这种行开始的代码会手动在行首加一个分号表示这是一个新的语句。此外在行合并时有个例外,就是return、break、continue这三个关键字组成的语句中不能有换行,看下面的代码:
return true;
上面的代码会解析为 return; true; 因为return、break、continue这三个关键字组成的语句不能有换行。最后一个问题就是前缀和后缀的自增自减运算符,如果为后缀运算符,则它必须和变量在同一行,看下面的代码:
x ++ y
会被解析为 x; ++y 而不是 x++; y 。
js的数据类型
虽然js属于弱类型语言,但其总共有6种数据类型。弱类型的意思是定义的变量没有类型的区分,比如先执行 var num=123; 定义了一变量num存储整数,可接下来执行 num="hello world"; 将字符串赋值给num变量并不会报错,是合法的。
js的弱类型相对于强类型的语言来说看起来好像很好用,其实也不尽然,下面列举了一些字符串和整数进行操作时候的一些因为js的弱类型带来的问题。
32 + 32 // 结果是 64 "32" + 32 // 结果是 "3232" "32" - 32 // 结果是 0
/*
值得一提的是基于上面的一些问题,这里出现了两个类型转换技巧
字符串转整数:num - 0;
整数转字符串:num + '';
*/
js中的六种数据类型
原始类型:①number;②string;③boolean;④null;⑤undefined
对象类型:⑥object(Function,Array,Date等都是object类型)
js中的数组与对象
数组和对象是js中特别重要的用于存储数据的一种类型,其中数组和对象分别用 [] 和 {} 表示没有任何 元素/属性 的 数组/对象 , 并且这两个东西都有一个特性就是动态添加。比如 var arr=[] 先定义了一个空的数组,之后使用 arr[0]='hello'; 语句可以向数组arr中添加元素。对于对象 var stu={} 先定义了一个没有属性的对象,之后可以使用 stu['name']='张三'; 添加name属性。而c语言和java语言中就会出错,在java中会报空指针异常。
关于数组和对象的具体用法我们将在后面的章节中详细介绍,这里只做简要说明。
js的隐式转换
因为js是弱类型,所以存在大量的隐式转换,其中下面的结果都是true
"1.23" == 1.23 //尝试将字符串转换为数字再比较 0 == false //将boolean值转换为数字再比较,其中false转为0,true转为1,
//所以1==true返回true,但是2==true返回false null == undefined
//如果是object==string|number会尝试将对象转换为基本类型 比如:new String('hi') == 'hi' 会
//返回true,其它情况会返回false。
这样一来就有人会问,那怎么保证 1.23 等于1.23 而不等于 "1.23" 呢?这个就引出了js中的一个新的运算符 === 严格等于运算符,这个运算符会先判断等号两边的类型是否相同,不同就直接返回false。如果类型相同且满足一下原则会返回true:
①数值满足值相等
②字符串满足长度和字符均相等
③null === null
④undefined === undefined
此外还有两个东西NaN和object,其中NaN和任何东西比较都是false,包括它自己,即NaN===NaN也返回false,而object是引用比较,只有是同一个对象才返回true。
js包装类型
如上图所示,虽然前面讲过string(不是String)属于基本类型,但是其依然有属性length,这看起来似乎有对象的影子,这其实是js的包装起的作用,每次在使用string、number等类型的变量时,js会自动对这些变量进行包装,创建出一个临时对象出来,图上所示在执行str.length时js偷偷执行new String(str).length了。
js类型检测
1、使用typeof检测类型
typeof 100 //返回 "number" typeof true //返回 "boolean" typeof function //返回 "function" typeof (undefined) //返回 "undefined" typeof new Object() //返回 "object" typeof [1,2] //返回 "object" typeof NaN //返回 "number" typeof null //返回 "object"
2、使用instanceof判断对象类型(格式:对象 instanceof 函数构造器)
[1,2] instanceof Array //返回true new Object() instanceof Array //返回false
3、使用Object.prototype.toString
Object.prototype.toString.apply([]); //返回 "[object Array]" Object.prototype.toString.apply(function(){}); //返回 "[object Function]" Object.prototype.toString.apply(null); //返回 "[object Null]" Object.prototype.toString.apply(undefined); //返回 "[object Undefined]"