变量
- ECMAScript的变量是松散类型的,所谓松散类型就是可以用来保存任何类型的数据。
- 每个变量仅仅是用于保存值的占位符。
- 不建议变量所保存值的类型,但这种操作在ECMAScript中完全有效
- var操作符定义的变量将成为定义该变量的作用域中的局部变量,也就是说,如果在函数中使用var定义一个变量,那么这个变量在函数退出后就会被销毁
function test(){
var message = 'hi'
}
test()
alert(message)
//message is not defined
- 可以使用一条语句定义多个变量,只要像下面这样把每个变量(初始化或不初始化均可)用逗号分开
var message = 'hi',
found = false,
age = 29
在严格模式下,不能定义名为eval或arguments的变量,否则会导致语法错误
typeof操作符
-
typeof操作符可能返回的字符串
1、'undefined'
2、'boolean'
3、'string'
4、'number'
5、'object'
6、'function' -
有时候typeof会返回一些令人迷惑但技术上却正确的值。
比如,调用type of null
会返回object,因为null被认为是一个空的对象引用
Undefined
- Undefined的类型只有一个值,即特殊的undefined。在使用var声明变量但未对其加以初始化时,这个变量的值就是undefined
var message
alert( message == undefined ) //true
等于
var message = undefined
alert( message == undefined ) //true
但是我们没必要这么做
- 但是包含undefined值的变量与尚未定义的变量还是不一样的
var message
alert(message) //'undefined'
alert(age) //错误
- 对未初始的变量执行typeof操作符会返回undefined值,而对未声明的变量执行typeof操作同样会返回undefined值
var message
alert(typeof message ) //'undefined'
alert(typeof age ) //错误
Null类型
- Null类型是第二个只有一个值的数据类型,这个特殊的值是null。从逻辑角度来看,null值表示一个空对象指针,而这也正是使用typeof操作符检测null值会返回'object'的原因。
- 如果定义的变量准备在将来用于保存对象,那么最好将该变量初始化为null而不是其他值
- 实际上,undefined值是派生自null值的,因此ECMA-262规定对 它们的相等性测试要返回true
alert(null == undefined) //true
null和undefined的用途完全不同,如果保存对象的变量还没有真正保存对象,就应该明确地让该变量保存null值,这样做不仅可以体现null作为空对象指针的惯例,而且也有助于进一步区分null和undefined
alert(null === undefined) //false
Boolean类型
- Boolean类型是ECMAScript中使用得最多的一种类型
- 该类型只有两个值,一个true,一个false
- true不一定等于1,而false也不一定等于0
- true 和 false是区分大小写的
- 要将一个值转换为其对应的Boolean值,可以调用转型函数Boolean()
var message = 'Hello world!'
var messageAsBoolean = Boolean(message)
- 下表给出了各种数据类型及其对应的转换规则
数据类型 | 转换为true的值 | 转换为false的值 |
---|---|---|
Boolean | true | false |
String | 任何非空字符串 | ' '(空字符串) |
Number | 任何非零数字值 | 0和NaN |
Object | 任何对象 | null |
Undefined | 不适用 | undefined |
Number类型
- 使用IEEE754格式来表示整数和浮点数值
- 最基本的数值字面量格式是十进制整数,十进制整数可以像下面这样直接在代码中输入
var intNum = 55 //整数
- 也可以八进制或者十六进制
- 八进制字面值的第一位必须是(0),然后是八进制数字序列(0~7),如果超出了范围,那么前导零将被忽略,后面的数值将被当做十进制数值解析
var octalNum1 = 070 //八进制的56
var octalNum2 = 079 //无效的八进制数值——解析为79
var octalNum3 = 08 //无效的八进制数值,解析为8
八进制字面量在严格模式下是无效的,会导致支持的JavaScript引擎抛出错误
- 十六进制的字面值的前两位必须为0x,后跟任何十六进制数字(0 ~ 9 及 A ~ F),字母A ~ F可以大写,也可以小写。
var hexNum1 = 0xA //十六进制的10
var hexNum2 = 0x1f //十六进制的31
浮点数值
- 所谓浮点数值,就是数值中必须包含一个小数点,并且小数点后面必须至少有一位数字。
var floatNum1 = 1.1
var floatNum2 = 0.1
var floatNum3 = .1
由于保存浮点数值需要的内存空间是保存整数值的两倍,因此ECMAScript会不失时机地将浮点数值转换成整数值
- 对于那些极大或极小的数值,可以用e表示法(即科学计数法)表示 的浮点数值表示。用e表示法表示的数值等于e前面的数值乘以10的指数次幂
var floatNum = 3.125e7 //等于31250000
- 浮点数值的最高精度是17位小数,但在进行算术计算是其精确度远远不如整数。
例如:0.1+0.2的结果不是0.3
这是使用基于IEEE754数值的浮点计算的通病
数值范围
- ECMAScript能够表示的最小数值保存在Number.MIN_VALUE中——在大多数浏览器中,这个值是5e-324
- 最大值保存在Number.MAX_VALUE中——在大多数浏览器中,这个值是1.7976931348623157e+308
- 如果某次计算的结果得到一个超出JavaScript数值范围的值,那么这个数值会被自动转换成特殊的Infinity值,分别为正Infinity和负Infinity
- 想要确定一个数是不是有穷的,可以使用isFinite()函数。这个函数位于最小与最大数值之间时会返回true
var result = Number.MAX_VALUE+Number.MAX_VALUE
console.log(isFinite(result)) //false
NaN
- NaN,即非数值(Not a Number)是一个特殊的数值,这个数值用于表示一个本来要返回数值的操作数未返回数值的情况。
- 任何涉及NaN的操作都会返回NaN
- NaN与任何值都不相等,包括NaN本身
console.log(NaN === NaN) //false
- 针对NaN的这两个特点,ECMAScript定义了isNaN()函数。isNaN在接收到一个值之后,会尝试将这个值转换为数值,而任何不能被转换为数值的值都会导致这个函数返回true
数值转换
-
有三个函数可以把非整数转换为数值
1、Number()
2、parseInt()
3、parseFloat() -
Number()函数的转换规则如下
1、如果是Boolean值,true和false将分别转换为1和0
2、如果是数字值,只是简单的传入和返回
3、如果是null值,返回0
4、如果是undefined,返回NaN
5、如果是字符串,则:- 如果字符串只包含数字,则将其转换为十进制数值,前导零忽略
- 如果字符串包含有效的十六进制格式,则将其转换为对应的十进制整数值
- 如果字符串是空的,则将其转换为0
- 如果字符串中包含除上述格式之外的字符,则将其转换为NaN
Sting类型
- ECMAScript中的字符串是不可变的,也就是说,字符串一旦创建,它们的值就不能改变。要改变某个变量保存的字符串,首先要销毁原来的字符串,然后再用另一个包含新值的字符串填充该变量
var lang ='Java'
lang = lang + 'Script'
实现这个操作的过程如下:
1、创建一个能容纳10个字符的新字符串
2、在这个字符串中填充'Java'和'Script'
3、销毁原来的字符串'Java'和字符串'Script'
销毁也是某些旧版本的浏览器中拼接字符串时速度很慢的原因所在
- 转换为字符串
1、使用toString()
但 null 和 undefined 值没有这个方法
2、转型函数String(),在不知道要转换的值是不是null或undefined的情况下,可以用这个函数,可以将任何类型的值转换为字符串。
var value1 = 10
var value2 = true
var value3 = null
var value4
alert(String(value1)) //'10'
alert(String(value2)) //'true'
alert(String(value3)) //'null'
alert(String(value4)) //'undefined'
Object类型
- ECMAScript中的对象其实就是一组数据和功能的集合。对象可以通过new操作符后跟要创建的对象类型的名称来创建。
而创建Objcet类型的实例为其添加属性、方法,就可以创建自定义对象
var o = new Object()
如果不传参的话,可以省略圆括号,但是不推荐
var o = new Object //有效,但是不推荐
Object类型是所有它的实例的基础。换句话说,Object类型所具有的任何数学和方法也同样存在于更具体的对象中
- Object的每个实例都具有下列属性和方法
1、Constructor:保存着用于创建当前对象的函数。对于前面的例子而言,构造函数(constructor)就是Object()
2、hasOwnProperty( propertyName ):用于检查给定的属性在当前对象实例中(而不是在实例的原型中)是否存在
3、isPrototypeOf( object ):用于检查传入的对象是否是另一个对象的原型
4、propertyIsEnumerable( propertyName ):用于检查给定的属性是否能够使用for-in语句来枚举
5、toLocaleString():返回对象的字符串表示
6、valueOf():返回对象的字符串、数值或布尔值表示。通常与toString()方法的返回值相同
操作符
一元操作符
- 递增,递减操作符
- 前置型和后置型
前置型
var age = 29
++age
与以下操作的效果相同
var age = 29
age = age + 1
递减操作符形式相同
执行前置递增和递减操作时,变量的值都是在语句被求值以前改变的。(在计算机科学领域,这种情况通常被称作副效应)
前置递增和递减操作与执行语句的优先级相等,因此整个语句会从左至右被求值
var num1 = 2
var num2 = 20
var num3 = --num1 + num2 //等于21
var num4 = num1 + num2 //等于21
后置递增和递减操作符,递增和递减操作是在包含他们的语句被求值之后才执行的
- 他们不仅适用于整数,还可以用于字符串、布尔值、浮点数值和对象。在应用不同的值时,递减和递增操作符遵循下列规则
1、在应用于一个包含有效数字字符的字符串时,将其转换为数字值,再执行加减1的操作。字符串变量变成数值变量
2、在应用于一个不包含有效数字字符的字符串时,将变量的值设置为NaN,字符串变量变成数值变量
3、在应用于布尔值是,先将其转换为0或1在执行加减1的操作。布尔变量变成数值变量
4、在应用于对象时,先调用对象的valueOf()方法以取得一个可供操作的值。如果结果是NaN,则在调用toString()方法后再应用前述规则。对象变量变成数值变量
位操作符
-
位操作符用于在最基本的层次上,即按内存中表示数值的位来操作数值。ECMAScript中的所有数值都以IEEE-75464位格式存储,但位操作符并不直接操作64位的值。而是先将64位转换为32位的整数,然后执行操作,最后再将结果转换回64位。对于开发人员来说,由于64位存储格式是透明的,因此整个过程就像是只存在32位的整数一样。在转换过程中也导致了一个严重的副效应,即在对特殊的NaN和Infinity值应用位操作时,这两个值都会被当成0来处理
-
负数同样以二进制码存储,但使用的格式是二进制补码。计算一个数值的二进制补码,需要经过下列3个步骤:
1、求这个数值绝对值的二进制码
2、求二进制反码,即将0替换为1,将1替换为0
3、得到的二进制反码加1
ECMAScript会尽力向我们隐藏所有这些信息,如下面代码所示
var num = -18 //1111 1111 1111 1111 1111 1111 1110 1110
alert(num.toString(2)) //'-10010'
按位非(NOT)
- 按位非操作由一个波浪线(~)表示,执行按位非的结果就是返回数值的反码。按位非是ECMAScript操作符中少数几个与二进制有关的操作符之一
var num1 = 25
var num2 = ~num1
alert(num2) //-26
按位与(AND)
- 按位与操作符由一个和号字符(&)表示,同样也有两个操作数。
- 简而言之,按位与操作只在两个数值的对应位都是1时才返回1,任何一位是0,结果都是0
var result = 25 & 3
alert(result) //1
按位或(OR)
- 按位或操作符由一个竖线符号(|)表示,同样也有两个操作数。
- 按位或操作在有一个位是1的情况下就返回1,而只在两个位都是0的情况下才返回0
var result = 25 | 3
alert(result) //27
按位异或(XOR)
- 按位异或操作符由一个插入符号(^)表示,也有两个操作数
- 这个操作在两个数值对应位上只有一个1时才返回1,如果对应的两位都是1或都是0,则返回0
var result = 25 ^ 3
alert(result) //26
左移
- 左移操作符由两个小于号(<<)表示,这个操作符会将数值的所有位向左移动指定的位数。
var oldValue = 2 //等于二进制的10
var newValue = oldValue << 5 //等于二进制的1000000,十进制的64
在向左移动后,原数值的右侧多出了5个空位。左移操作会以0来填充这些空位,以便得到的结果是一个完整的32位二进制数
无符号的右移
var oldValue = 64
var newValue = oldValue >>> 5
- 无符号的右移跟左侧同理,但是对负数来说,情况就很不一样了。首先,无符号右移是以0来填充空位,而不是像有符号右移那样以符号位的值来填充空位。
- 无符号右移操作会把这个二进制码当成正数的二进制码。
有符号的右移
保留符号位
var oldValue = 64
var newValue = oldValue >> 5
布尔操作符
布尔操作符一共有3个:非(NOT)、与(AND)和或(OR)
-
逻辑非(!)
同时使用两个逻辑非操作符,实际上就会模拟Boolean()转型函数的行为 - 逻辑与(&&)
var result = true && false
他遵循下列规则:
第一个操作数 | 第二个操作数 | 结果 |
---|---|---|
对象 | - | 第二个操作数 |
true | 对象 | 第二个操作数 |
false | 对象 | - |
对象 | 对象 | 第二个操作数 |
如果一个操作数是null、NaN、undefined则返回null、NaN、undefined
不能在逻辑与操作中使用未定义的值。
var found = true
var result = (found && someUndefinedVariable) //发生错误
alert(result) //不会执行
逻辑或( || )
遵循的规则与逻辑与相似
如果两个操作数都是null、NaN、undefined则返回null、NaN、undefined
var found = false //false
var result = (found || someUndeFinedVariable) //会发生错误
alert(result) //不会执行
乘性操作符
乘法
如果参加乘法计算的某个操作数不是数值,后台会先使用Number()转型函数将其转换为数值
var result = 34 * 56
在处理特殊值的情况下:
1、如果有一个操作数是NaN,则结果是NaN
2、如果是Infinity与0相乘,则结果是NaN
3、如果Infinity与非0数值相乘,则结果是Infinity或-Infinity
4、如果不是数值,则在后台调用Number()将其转换为数值
除法
var result = 66 / 11
在处理特殊值的情况下:
1、如果有一个操作数是NaN,则结果是NaN
2、如果有一个操作数是NaN,则结果是NaN
3、如果是Infinity被Infinity除,则结果是NaN
4、如果零被零除,则结果是NaN
5、如果是非零的有限数被零除,则结果是Infinity或-infinity
6、如果不是数值,则在后台调用Number()将其转换为数值
相等操作符
ECMAScript的解决方案就是提供两组操作符:
相等和不相等
- 强制转型
- null 和 undefined 是相等的
- NaN跟任何值都不相等,包括NaN
全等和不全等
for-in循环
- ECMAScript对象的属性没有顺序。因此,通过for-in循环输出的属性名是不可预测的。具体来讲,所有属性都会被返回一次。
- 但是,如果表示要迭代的对象的变量值为 null 或 undefined,for-in语句会抛出错误
ES5更正了这一行为:对这种情况不再抛出错误,而只是不执行循环体
函数
- ECMAScript中的参数在内部是用一个数组表示的。
- 在函数体内可以通过arguments对象来访问这个参数数组,从而获取传递给函数的每一个参数
function sayHi(name, message){
alert('Hello' + name + ',' + message)
}
与下面的函数相等
function sayHi(){
alert('Hello' + arguments[0] + ',' + arguments[1])
}
- 命名的参数只提供便利,但不是必需的
- arguments对象的长度是由传入的参数个数决定的,不是由定义函数时的命名参数的个数决定的
没有重载
- 不能像传统意义上那样实现重载。而在其他语言中,可以为一个函数编写两个定义,只要这两个定义的签名不同即可
- ECMAScript函数没有签名,因为其参数是包含零或者多个值的数组来表示的
- 如果定义了两个名字相同的函数,则该名字只属于后定义的函数
网友评论