3.1 语法
3.1.1 区分大小写
ECMAScript区分大小写;
3.1.2 标识符
定义:变量,函数,属性的名字,或者函数的参数名。
规则:首字符由字母,下划线或者美元符号组成。其它字符则再加上一个数字。可包含ASCII和Unicode字母字符,但是不推荐。最后,标识符采用驼峰大小格式。
3.1.3 注释
// /**/
3.1.4 严格模式
定义:严格模式主要是为JavaScript定义一种不同的解析和执行模型;Use strict
延伸点:这里就涉及到严格模式和混杂模式的关系。
首先,需要介绍一个定义:Doctype,
声明叫做**文件类型定义**(DTD),声明的作用为了告诉浏览器该文件的类型。让浏览器解析器知道应该用哪个规范来解析文档。声明必须在 HTML 文档的第一行,这并不是一个 HTML 标签。**严格模式:**又称标准模式,是指浏览器按照 W3C 标准解析代码。
**混杂模式:**一种比较宽松的向后兼容的模式。混杂模式通常模拟老式浏览器的行为,以防止老站点无法工作。
**如何区分:**与网页中的 DTD 直接相关。
- 1、如果文档包含严格的 DOCTYPE ,那么它一般以严格模式呈现。(严格 DTD ——严格模式)
- 2、包含过渡 DTD 和 URI 的 DOCTYPE ,也以严格模式呈现,但有过渡 DTD 而没有 URI (统一资源标识符,就是声明最后的地址)会导致页面以混杂模式呈现。(有 URI 的过渡 DTD ——严格模式;没有 URI 的过渡 DTD ——混杂模式)
- 3、DOCTYPE 不存在或形式不正确会导致文档以混杂模式呈现。(DTD不存在或者格式不正确——混杂模式)
- 4、HTML5 没有 DTD ,因此也就没有严格模式与混杂模式的区别,HTML5 有相对宽松的语法,实现时,已经尽可能大的实现了向后兼容。( HTML5 没有严格和混杂之分)
3.1.5 语句
语句结束最好使用;结尾和代码块,不完整的输入可能会导致压缩错误。
3.2 关键字和保留字
instanceof关键字:用来判断对象是否是指定构造函数的实例。只要构造函数的原型对象出现在实例对象的原型链中都会返回true。(可以在后面原型链那一章再具体延伸一些)
let p = new Person();
console.log(p instanceof Person);
let保留字,es6中已经成为了关键字,用于声明变量。其与var的区别在于:
1.let声明只会作用于块级作用域,外层作用域无法获取到内层作用域,即使外层和内层都使用相同变量名。当前值不会影响下一次的循环,循环后的值不会改变之前的值。
var arr = [ ];
for(var i=0; i<10; i++){
arr [i] = function(){//输入8后,因为i<10,还会进入循环
alert(i)
}
}
arr [8](); 结果是10 最后一次
var arr = [ ];
for(let i=0; i<10; i++){
arr[i] = function(){//i只会作用于当前块级作用域
alert(i)
}
}
arr[8](); //结果:8
2,不会出现变量提升的现象,因为其作用域是块级作用域。
需注意的是:let声明过程中:
1.不要重复声明变量;
2.不要重复声明函数参数;
yield保留字,es6中为关键字,用于暂停和恢复一个生成器函数。相当于基于生成器版本的return关键字。
yield关键字实际返回一个IteratorResult对象,它有两个属性,value和done。value属性是对yield表达式求值的结果,而done是false,表示生成器函数尚未完全完成。
一旦遇到 yield 表达式,生成器的代码将被暂停运行,直到生成器的 next() 方法被调用。每次调用生成器的next()方法时,生成器都会恢复执行,直到达到以下某个值:
yield,导致生成器再次暂停并返回生成器的新值。 下一次调用next()时,在yield之后紧接着的语句继续执行。throw用于从生成器中抛出异常。这让生成器完全停止执行,并在调用者中继续执行,正如通常情况下抛出异常一样。- 到达生成器函数的结尾;在这种情况下,生成器的执行结束,并且
IteratorResult给调用者返回undefined并且done为true。 - 到达
return语句。在这种情况下,生成器的执行结束,并将IteratorResult返回给调用者,其值是由return语句指定的,并且done为true。
注意事项:如果使用了关键字作标识符,则会导致“Identifier Expected”错误。使用保留字是否出现相同错误,要视引擎为准。关键字和保留字不能作为标识符,但现在可以用作对象的属性名;最好为了兼容不要使用。
Eval和arguments不是关键字也不是保留字,在ECMA第5版中,也被限制,不能作为标识符或者属性名,否则抛出错误。
eval:js中的一个方法,接受一个字符串作为参数,并将这个参数作为脚本代码执行。eval(string)
arguments:js的一个内置对象。每一个函数都有一个arguments对象,它包括了函数所要调的参数,通常我们把它当作数组使用,用它的length得到参数数量,但它却不是数组。
3.3 变量
松散类型:可以用来保存任何类型的数据。而ECMAScript变量即为松散变量,其变量仅仅是用于保存值的占位符;若没有给定初始值,则为undefined。
由于变量是松散类型的,所以可以改变原本变量的类型,但是不推荐。
需注意:
用var 操作符定义的变量将成为该变量作用域中的局部变量,离开原本作用域后就会被销毁。而不加var声明,就会创建一个全局变量(即未经声明的变量)。但是这种方式不推荐,因为局部作用域中的全局变量很难维护,因为该变量不会马上有定义造成混乱,严格模式下会导致referenceError错误。
由于变量是松散类型的,所以可以一个语句中声明多个不同变量。
严格模式下,不能定义名为eval或arguments的变量,否则会引起错误。
延伸点:
1.全局变量和局部变量的问题,作用域的问题。
2.this指向的问题。
3.4 数据类型(重点)
包含Number,String,Boolean,Null,Undefined,Symbol六种基本数据类型和一种引用类型Object。
3.4.1 typeof操作符
Typeof的缺点:Typeof操作符可以用于判断数据类型,但是其不能判断引用类型的详细类型,它可以判断function为函数类型。
1. 不能区分null和object,会将null判断成object,但是null不能使用对象的一些操作。
2. 对NaN返回的是number类型,但是NaN不能进行算术运算。
3. 其不能判断出数组,正则表达式(有的老版本会识别成function),不能区分数组,正则表达式和object,会将数组判断成object。
4. 对未初始化和未声明的变量执行typeof操作符都返回undefined。
3.4.2 undefined
undefined正式用于区分空对象指针与未经初始化的变量。
未初始化和未声明变量直接输出的结果是不同的,前者返回undefined,后者则会报错。
但是这两种变量用typeof输出结果是一样的。
3.4.3 null
表示的是一个空对象指针,用于保存对象。
Null和undefined使用==返回为true,但是使用全等于===则不同,因为==操作符出于比较目的会转换其操作数(转换操作数类型)。
3.4.4 Boolean类型
字面量为true和false,区分大小写。另外true和1,false和0不一定相等。
使用Boolean()转型函数,可以返回相应的Boolean值。
3.4.5 number类型
不同进制数的表示方法:八进制(第一位为0,严格模式下无效),十六进制(前两位为0x)。
1.浮点数的存储,表示和计算。
浮点数的存储:保存浮点数的内存空间是保存整数值的两倍。
浮点数的计算:0.1+0.2不等于0.3
浮点数的表示:可以使用e表示法(大小写e均可)
2.数值范围:
数值范围为正负无穷。用正负infinity来表示。其中可以用isFinite()函数来对变量进行判断。
Number.MAX_VALUE得到的是正无穷的数值,而使用Number.POSITIVE_INFINITY得到的是Infinity
3.NaN
表示一个本来要返回数值的操作数未返回数值的情况。
关于NaN的操作和计算:任何值除以NaN均为NaN(其它操作在后面操作符中有)。
NaN和自身并不相等。
可以使用isNaN()函数来判断参数是否为数值。可以对Boolean值和字符串,数值进行判断。
4. 数值转换
Number(),parseInt(),parseFloat()
转型函数Number()可以用于任何数据类型,其它两个函数是把字符串转换成数值。parseInt用于将数据转换成整数(可以表示不同进制),parseFloat用于将数据转换成浮点数(只对十进制数进行处理,非十进制转换为0)。
Number()转换规则:
Number类型即为原本数值;
Boolean值true为1,false为0;
Undefined转换成NaN;
Null转换成0;
String类型则分情况:全数字的字符串转换为对应数值,字符串为空则转换成0,浮点格式或十六进制模式则转换成其对应浮点数值和十进制值。其它则转换成NaN。
对象:先调用valueof()方法,如果转换的结果是NaN,则继续调用对象的toString()方法。
给定第二个参数作为转换时使用的基数,即多少进制。空字符串转换成NaN;
parseFloat()函数:
与parseInt()函数功能类似,字符串的第一个小数点有效;但是不支持8和16进制数值的转换,只支持10进制,遇到16进制数会转换成0。
3.4.6 string类型
由字符生成的转义序列表示一个字符。
字符串的特点:字符串是不可变的,如果想改变某个变量保存的字符串,首先要销毁原来的字符串,再用另一个包含新值的字符串去填充该变量。
转换字符串的方法:toString()。可以传入参数表示基数(进制),这个方法的缺点是:null和undefined值没有该方法。如果要对null和undefined进行转换,则需使用String()函数。
3.4.7 object类型
一组数据和功能的集合,详细点需看第五章。
3.5 操作符
3.5.1 一元操作符
一元操作符包括递增递减操作符,一元加和减操作符两种。
1.递增和递减操作符
分前置型和后置型两种,两者计算有些许不同。执行前置递增和递减操作时,变量值在语句被求值以前改变。(即在当前语句运算结束后,变量和当前语句的新变量值都会改变)。而后置递增和递减,是在包含它们的语句被求值之后才执行的。
Var num = 20;
Var num2 = num++ + 2;
Var num3 = num + 2;
alert(num2); 22 语句2结束之后num才执行递增操作,之前值不改变
alert(num3);23
递增和递减操作符,对于null和undefined没有操作,但是可适用于布尔值,数值,字符串和对象。其转换规则和number函数有点类似,对对象都是先用对象的valueOf方法,如果得到NaN,则使用toString方法,再进行递增和递减操作。
2.一元加和减操作符
一元加操作符以一个加号+表示(类似+num),放在数值前,对数值不会产生任何影响。
Num2 = +num;num2的值和num相同。
而一元加操作符的使用作用,其实和number()函数类似。即对非数值数进行转换计算。
一元减操作符主要是应用于表示负数。(转换规则与一元加操作符类似。)
3.4.2 位操作符
ECMAScript中的所有数值都是以64位格式存储。位操作符不能直接操作64位数;而是先将64位数转换成32位,执行操作后,再转换成64位。
对于有符号的整数,第32位作为符号位,1到31位作为整数值的表示位。其中,如果是负数,则使用反码,需要注意的是,处理有符号整数时,是不能访问位31的即符号位。另外,ECMASript会尽量隐藏数值变换信息,也就是说,当我们用二进制字符串来输出一个负数时,它会显示这个数的绝对值二进制数加负号,再用引号引用。
Var num = -18;
alert(num.toString(2)); 输出的时“-10010”
由于ECMAScript中执行位操作符时,先将数值从64位转换成32位,操作后再转换成64位,会导致将特殊的NaN和无穷大Infinity执行位操作时,将这两个值当成0来处理。
对于非数值应用位操作符,先使用number()函数转换,再执行位操作符。
位操作符包括:按位非,按位与,按位或,按位异或,左移,有符号的右移和无符号右移这七种。(NOT(~),AND(&),OR(|),XOR(^),<<,>>,>>>)
按位非:操作数的负值减一。(因为该值改变后,符号位改变,要变成原本的负数需要用反码并执行加1操作才能变成原本的数的负数。所以就变成操作数的负值减一。)
按位与:每一位对齐,进行与操作。
按位或与按位异或,与前面说的类似。
左移不会影响操作数的符号位,空出位用0来代替。
有符号右移,则会用符号位的数值来代替空出位。
无符号右移(>>>表示), 以0来补充空位,而且会将负数的二进制码当成正数的二进制码。
3.4.3 布尔操作符(可以应用于任何类型的操作数)
布尔操作符有三种:逻辑非(!),逻辑与(&&),逻辑或(||)
其中,逻辑与的操作规则会比较麻烦,因为其可以应用于任何类型的操作数。遵循的规则可概括为:
当涉及对象时:如果第一个操作数时对象,则返回第二个操作数。如果第二个操作数是对象,则只有第一个操作数是true时返回对象,如果两个都是对象,则返回第二个对象。
如果第一个操作数时null,NaN,undefined,则返回相应数。
不能在逻辑与操作中使用未定义的值。其属于短路操作符,如果第一个操作数时false,则不会再考虑第二个操作数。逻辑或和逻辑与则类似。
3.4.4 乘性操作符
包括乘法,除法和求模三种。如果操作数非数值,则会先使用number()函数转换。
3.4.5 加性操作符
分为加法和减法两种。
在加法中:如果两个操作数都是数值,则进行数值计算。其中包括NaN,Infinity,+0和-0等特殊数值计算。**如果有一个操作数是字符串,另一个操作数是对象,数值或布尔值,则调用toString()方法。**对于null和undefined则使用string()方法。如果一个数是数值,一个是对象,数组或布尔值,则先用number()方法将其转换成数值型再计算。
在减法中:则是将非数值操作数用number()方法进行转换。
3.4.6 关系操作符
分为小于(<),大于(>),小于等于(<=)和大于等于(>=)这四种。
如果两个操作数是数值,则直接比较;
如果两个操作数都是字符串,则依次比较每位上的字母的ASCII值。
如果有一个是数值,则将另外一个操作数转换成数值。
如果是对象,则调用valueOf,进行比较。如果没有valueOf方法,则使用toString方法。
需注意:
1.“23”<”3”这种情况,因为两个操作数都是字符串,所以使用第二个点。(因为“23”编码要小于“3”的字符编码)
2.“a”<3 这种情况,先用number方法将字符串“a”转换,得到结果NaN,而所有的数都不能和NaN比较。
3.5.7 相等操作符
1.相等和不相等:特点是先转换再比较(强制转型,但是如果操作数是同种类型,则不需要转换)
2.全等和不全等:特点是数据类型相等,值相等。
3.5.8 条件操作符
(a>b?a:b;)
3.5.9 赋值操作符
(=,复合赋值操作符)
3.5.10 逗号操作符
用于声明多个变量,另外,可以用于赋值。(返回表达式中的最后一项)
3.6 语句
If语句,do-while语句(后测试循环语句),while语句(前测试循环语句),for语句,for-in语句(用来枚举对象的属性,对于变量值为null或undefined的不再执行循环体,最好提前检测该对象值不是null或undefined),label语句(在代码中添加标签,一般和for语句等循环语句配合使用),break和continue语句(break是立即退出循环,而continue是退出本次循环,但是下次循环仍然继续,一直到不满足循环条件;而如果有嵌套循环,break是退出内部和外部循环,而continue是退出内部循环,执行外部循环),with语句(简化多次编写同一对象,不推荐使用),switch语句(如果省略break关键字,则会继续执行下一个case,另外case的值可以是常量,变量或者表达式,而且比较值时使用的是全等操作符)。
3.7 函数
函数内部含有return语句,return语句可以不带有任何返回值(停止执行后将返回undefined),并且其后面的语句将不会再执行。
严格模式下对函数有一些限制:不能将函数或者参数命名为eval或arguments,不同参数不能同名。
3.7.1 理解参数
ECMAScript函数不介意传参,因为其参数在内部是用一个数组表示的,其没有函数签名。
函数签名:
arguments对象的使用:其可以计算出传入的参数的长度(arguments对象的长度由实参个数决定,不是由形参决定),可以通过arguments[]的方式来获取传入的参数,并且arguments对象中的值会自动反映到对应的命名参数。但是,它们的内存空间是不同的,并不是会访问到相同的内存空间。需注意:
1.如果只传入一个参数,那arguments[1]设置的值不会反映到命名参数中。
2.没有传递值的命名参数(形参)将自动被赋予undefined值。
严格模式下,arguments赋值会失效,而且重写arguments会导致语法错误。
3.7.2 没有重载
因为没有函数签名,所以ECMAScript没有重载。当定义相同名字的函数时,后定义的会覆盖之前定义的。