《JavaScript高级程序设计》读书笔记-第三章(基本概念)

《JavaScript高级程序设计》读书笔记-第三章(基本概念)_第1张图片

变量

  • ECMAScript的变量是松散类型的,所谓松散类型就是可以用来保存任何类型的数据。
  • 每个变量仅仅是用于保存值的占位符。
  • 不建议变量所保存值的类型,但这种操作在ECMAScript中完全有效
  • var操作符定义的变量将成为定义该变量的作用域中的局部变量,也就是说,如果在函数中使用var定义一个变量,那么这个变量在函数退出后就会被销毁
function test(){
  var message = 'hi'
}
test()
alert(message)
//message is not defined
  • 可以使用一条语句定义多个变量,只要像下面这样把每个变量(初始化或不初始化均可)用逗号分开
 var message = 'hi',
     found   = false,
     age     = 29 

在严格模式下,不能定义名为evalarguments的变量,否则会导致语法错误

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()
    nullundefined 值没有这个方法
    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循环输出的属性名是不可预测的。具体来讲,所有属性都会被返回一次。
  • 但是,如果表示要迭代的对象的变量值为 nullundefined,for-in语句会抛出错误
    ES5更正了这一行为:对这种情况不再抛出错误,而只是不执行循环体

函数

  • ECMAScript中的参数在内部是用一个数组表示的
  • 在函数体内可以通过arguments对象来访问这个参数数组,从而获取传递给函数的每一个参数
function sayHi(name, message){
  alert('Hello' + name + ',' + message)
}

与下面的函数相等

function sayHi(){
  alert('Hello' + arguments[0] + ',' + arguments[1])
}
  • 命名的参数只提供便利,但不是必需的
  • arguments对象的长度是由传入的参数个数决定的,不是由定义函数时的命名参数的个数决定的
没有重载
  • 不能像传统意义上那样实现重载。而在其他语言中,可以为一个函数编写两个定义,只要这两个定义的签名不同即可
  • ECMAScript函数没有签名,因为其参数是包含零或者多个值的数组来表示的
  • 如果定义了两个名字相同的函数,则该名字只属于后定义的函数

你可能感兴趣的:(《JavaScript高级程序设计》读书笔记-第三章(基本概念))