JavaScript高级程序设计 (读书笔记1)

1.
ECMAScript的解释程序遇到未声明过的标识符时,用该变量名创建一个全局变量,并将其初始化为指定的值。如 sMytest2

var sMytest = "hello";
sMytest2 = sMytest + "welcome";

这是该语言的便利之处,不过如果不能紧密跟踪变量,这样做也很危险。最好的习惯是像使用其他程序设计语言一样,总是声明所有变量

2.
在ECMAScript中,变量可以存放两种类型的值,即原始值和引用值。

原始值(primitive value)是存储在栈(stack)中的简单数据段,也就是说,它们的值直接存储在变量访问的位置。

引用值(reference value)是存储在堆(heap)中的对象,也就是说,存储在变量处的值是一个指针(point),指向存储对象的内存处。

为变量赋值时,ECMAScript的解释程序必须判断该值是原始类型的,还是引用类型的。
要实现这一点,解释程序则需尝试判断该值是否为ECMAScript的原始类型之一,即Undefined、Null、Boolean和String型。
由于这些原始类型占据的空间是固定的,所以可将它们存储在较小的内存区域——栈中。这样存储便于迅速查寻变量的值。

在许多语言中,字符串都被看作引用类型,而非原始类型,因为字符串的长度是可变的。ECMAScript打破了这一传统。

如果一个值是引用类型的,那么它的存储空间将从堆中分配。
由于引用值的大小会改变,所以不能把它放在栈中,否则会降低变量查寻的速度。
相反,放在变量的栈空间中的值是该对象存储在堆中的地址。地址的大小是固定的,所以把它存储在栈中对变量性能无任何负面影响。


3.
ECMAScript有5种原始类型(primitive type),即Undefined、Null、Boolean、Number和String

ECMAScript提供了typeof运算符来判断一个值是否在某种类型的范围内。可以用这种运算符判断一个值是否表示一种原始类型;如果它是原始类型,还可以判断它表示哪种原始类型。

对变量或值调用typeof运算符将返回下列值之一:

"undefined",如果变量是Undefined型的。

"boolean",如果变量是Boolean型的。

"number",如果变量是Number型的。

"string",如果变量是String型的。

"object",如果变量是一种引用类型或Null类型的。

注意:你也许会问,为什么typeof运算符对于null值会返回"object"。这实际上是JavaScript最初实现中的一个错误,然后被ECMAScript沿用了。现在,null被认为是对象的占位符,从而解释了这一矛盾,但从技术上来说,它仍然是原始值。


3.1 Undefined类型
Undefined类型只有一个值,即undefined。当声明的变量未初始化时,该变量的默认值是undefined。
typeof 对于 未定义 和 定义未赋值 都是 是返回 undefind
var oTemp;

alert(typeof oTemp);// return undefined;
alert(typeof oTemp2);// return undefined;

3.2 Null类型
值undefined实际上是从值null派生来的
alert(null == undefined);

但是
undefined是声明了变量但未对其初始化时赋予该变量的值,
null则用于表示尚未存在的对象。

如果函数或方法要返回的是对象,那么找不到该对象时,返回的通常是null。

3.3 Number类型

ECMA-262中定义的最特殊的类型是Number型。这种类型既可以表示32位的整数,还可以表示64位的浮点数。

整数也可以被表示为八进制(以8为底)或十六进制(以16为底)的字面量。
八进制字面量的首数字必须是0,其后的数字可以是任何八进制数字(0到7),

要创建十六进制的字面量,首位数字必须为0,其后接字母x,然后是任意的十六进制数字(0到9和A到F)。这些字母可以是大写的,也可以是小写的。

尽管所有整数都可表示为八进制或十六进制的字面量,但所有数学运算返回的都是十进制结果。

要定义浮点值,必须包括小数点和小数点后的一位数字(例如,用1.0而不是1)。这被看作浮点数字面量。

浮点字面量的有趣之处在于,用它进行计算前,真正存储的是字符串。


ECMAScript默认把具有6个或6个以上前导0的浮点数转换成科学记数法。

也可用64位IEEE 754形式存储浮点值,这意味着十进制值最多可以有17个十进制位。17位之后的值将被截去,从而造成一些小的数学误差。

几个特殊值也被定义为Number类型的。

前两个是Number.MAX_VALUE和Number.MIN_ VALUE,
它们定义了Number值集合的外边界。所有ECMAScript数都必须在这两个值之间。
不过计算生成的数值结果可以不落在这两个数之间。

当计算生成的数大于Number.MAX_VALUE时,它将被赋予值Number.POSITIVE_INFINITY,意味着不再有数字值。
同样,生成的数值小于Number.MIN_VALUE的计算也会被赋予值Number.NEGATIVE_INFINITY,也意味着不再有数字值。
如果计算返回的是无穷大值,那么生成的结果不能再用于其他计算。

事实上,有专门的值表示无穷大,即Infinity。
Number.POSITIVE_INFINITY的值为Infinity,
Number.NEGATIVE_INFINITY的值为-Infinity。

由于无穷大数可以是正数也可以是负数,所以可用一个方法判断一个数是否是有穷的(而不是单独测试每个无穷数)。
可以对任何数调用isFinit()方法,以确保该数不是无穷大。

最后一个特殊值是NaN,表示非数(Not a Number)。NaN是个奇怪的特殊值。
一般说来,这种情况发生在类型(String、Boolean等)转换失败时。
例如,要把单词blue转换成数值就会失败,因为没有与之等价的数值。

与无穷大值一样,NaN也不能用于算术计算。
NaN的另一个奇特之处在于,它与自身不相等,这意味着下面的代码将返回false:
alert(NaN == NaN);//return false

出于这种原因,不推荐使用NaN值本身。函数isNaN()会做得相当好:
alert(isNaN("blue"));//true
alert(isNaN("123"));//false

3.4 String类型

String类型的独特之处在于,它是唯一没有固定大小的原始类型。可以用字符串存储0或更多的Unicode字符,由16位整数表示(Unicode是一种国际字符集,本书后面将讨论它)。

字符串中每个字符都有特定的位置,首字符从位置0开始,第二个字符在位置1,依此类推。这意味着字符串中的最后一个字符的位置一定是字符串的长度减1。

字符串字面量是由双引号(")或单引号(')声明的。与Java不同的是,双引号用于声明字符串,单引号用于声明字符。但是,由于ECMAScript没有字符类型,所以可使用这两种表示法中的任何一种。


4 类型转换

4.1 转换成字符串
总而言之,3种主要的原始值Boolean值、数字和字符串都有toString()方法,可以把它们的值转换成字符串。

也许你会问,“字符串还有toString()方法,这不是多余的吗?”
是的,的确如此,不过ECMAScript定义所有对象都有toString()方法,无论它是伪对象,还是真的对象。
因为String类型属于伪对象,所以它一定有toString()方法。

Boolean型的toString()方法只是输出"true"或"false",结果由变量的值决定

4.2 转换成数字
Number类型的toString()方法比较特殊,它有两种模式,即默认模式和基模式。

采用默认模式,toString()方法只是用相应的字符串输出数字值(无论是整数、浮点数还是科学记数法),
Number类型的toString()方法返回的都是数字的十进制表示。
因此,以八进制或十六进制字面量形式声明的数字输出时都是十进制形式的。

采用Number类型的toString()方法的基模式,可以用不同的基输出数字,
例如二进制的基是2,八进制的基是8,十六进制的基是16。
基只是要转换成的基数的另一种叫法而已,它是toString()方法的参数
var oTemp = 10;
alert(oTemp.toString(2));//return 1010
alert(oTemp.toString(8));//return 12
alert(oTemp.toString(16));//return A
HTML采用十六进制数表示每种颜色,在HTML中处理数字时这种功能非常有用。


ECMAScript提供了两种把非数字的原始值转换成数字的方法,即parseInt()和parseFloat()。
正如你可能想到的,前者把值转换成整数,后者把值转换成浮点数。
只有对String类型调用这些方法,它们才能正确运行;
对其他类型返回的都是NaN。


例如,如果要把字符串"1234blue"转换成整数,那么parseInt()将返回1234,因为当它检测到字符b时,就会停止检测过程。
字符串中包含的数字字面量会被正确转换为数字,因此字符串"0xA"会被正确转换为数字10。
不过,字符串"22.5"将被转换成22,因为对于整数来说,小数点是无效字符。


parseInt()方法还有基模式,可以把二进制、八进制、十六进制或其他任何进制的字符串转换成整数。
基是由parseInt()方法的第二个参数指定的,所以要解析十六进制的值,需如下调用parseInt()方法:
var iNum = parseInt("AF",16);
var iNum = parseInt("10",2);
var iNum = parseInt("10",8);
var iNum = parseInt("10",10);

parseFloat()方法与parseInt()方法的处理方式相似,从位置0开始查看每个字符,直到找到第一个非有效的字符为止,然后把该字符之前的字符串转换成数字。不过,对于这个方法来说,第一个出现的小数点是有效字符。如果有两个小数点,第二个小数点将被看作无效的,parseFloat()方法会把这个小数点之前的字符串转换成数字。这意味着字符串"22.34.5"将被解析成22.34。

使用parseFloat()方法的另一不同之处在于,字符串必须以十进制形式表示浮点数,而不能用八进制形式或十六进制形式。该方法会忽略前导0,所以八进制数0908将被解析为908。对于十六进制数0xA,该方法将返回NaN,因为在浮点数中,x不是有效字符。此外,parseFloat()也没有基模式。

4.3 强制类型转换
ECMAScript中可用的3种强制类型转换如下:

Boolean(value)——把给定的值转换成Boolean型;

当要转换的值是至少有一个字符的字符串、非0数字或对象(下一节将讨论这一点)时,Boolean()函数将返回true。
如果该值是空字符串、数字0、undefined或null,它将返回false。

Number(value)——把给定的值转换成数字(可以是整数或浮点数);

Number()的强制类型转换与parseInt()和parseFloat()方法的处理方式相似,只是它转换的是整个值,而不是部分值。
还记得吗,parseInt()和parseFloat()方法只转换第一个无效字符之前的字符串,因此"4.5.6"将被转换为"4.5"。
用Number()进行强制类型转换,"4.5.6"将返回NaN,因为整个字符串值不能转换成数字。
如果字符串值能被完整地转换,Number()将判断是调用parseInt()方法还是调用parseFloat()方法。

String(value)——把给定的值转换成字符串。

强制转换成字符串和调用toString()方法的唯一不同之处在于,对null或undefined值强制类型转换可以生成字符串而不引发错误:

5 Object类
Object类中的所有属性和方法都会出现在其他类中,所以理解了Object类,就可以更好地理解其他类。

Object类具有下列属性:

Constructor——对创建对象的函数的引用(指针)。对于Object类,该指针指向原始的object()函数。

Prototype——对该对象的对象原型的引用。对于所有的类,它默认返回Object对象的一个实例。

Object类还有几个方法:

HasOwnProperty(property)——判断对象是否有某个特定的属性。必须用字符串指定该属性(例如,o.hasOwnProperty("name"))。

IsPrototypeOf(object)——判断该对象是否为另一个对象的原型。

PropertyIsEnumerable(property)——判断给定的属性是否可以用for…in语句(本章后面将讨论该语句)进行枚举。

ToString()——返回对象的原始字符串表示。对于Object类,ECMA-262没有定义这个值,所以不同的ECMAScript实现具有不同的值。

ValueOf()——返回最适合该对象的原始值。对于许多类,该方法返回的值都与toString()的返回值相同。

上面列出的每种属性和方法都会被其他类覆盖。


6 Boolean类
遗憾的是,在ECMAScript中很少使用Boolean对象,即使使用,也不易理解。
问题通常出现在Boolean表达式中使用Boolean对象时。
var oFalseObject = new Boolean(false);
var bResult = oFalseObject && true;// outputs true

在这行代码中,计算的是oFalseObject,而不是它的值false。
正如前面讨论过的,在Boolean表达式中,所有对象都会被自动转换为true,所以oFalseObejct的值是true。
然后true再与true进行AND操作,结果为true。

虽然你应该了解Boolean对象的可用性,不过最好还是使用Boolean原始值,避免发生这一节提到的问题。

7 Number类

Number类是Number原始类型的引用类型。要创建Number对象,采用下列代码:
var oNumberObject = new Number(55);

你应该已认出本章前面小节中讨论特殊值(如Number.MAX_VALUE)时提到的Number类。
所有特殊值都是Number类的静态属性。

要得到数字对象的Number原始值,只需要使用valueOf()方法:
oNumberObject.valueOf();

toFixed()方法返回的是具有指定位数小数的数字的字符串表示。例如:
var oNumberObject = new Number(99);
alert(oNumberObject.toFixed(2));//return 99.00

这里,toFixed()方法的参数是2,说明了应该显示几位小数。该方法将返回"99.00",空的小数位由0补充。
对于处理货币的应用程序,该方法非常有用。
toFixed()方法能表示具有0到20位小数的数字,超出这个范围的值会引发错误。

toExponential()它返回的是用科学记数法表示的数字的字符串形式。toExponential()方法也有一个参数,指定要输出的小数的位数。例如
var oNumberObject = new Number(99);
alert(oNumberObject.toExponentital(1));//return 9.9e+1
这段代码的结果是输出"9.9e+1",前面解释过,它表示9.9×101。


问题是,如果不知道要用哪种形式(预定形式或指数形式)表示数字怎么办?
可以使用toPrecision()方法。

toPrecision()方法根据最有意义的形式来返回数字的预定形式或指数形式。它有一个参数,即用于表示数的数字总数(不包括指数)。例如:
var oNumberObject = new Number(99);
alert(oNumberObject.toPrecision(1));//return 1e+2
这段代码的任务是用一位数字表示数99,结果为"1e+2",以另外的形式表示即100。
的确,toPrecision()方法会对数进行舍入,从而得到尽可能接近真实值的数。
由于用2位以下数字不可能表示99,所以必须进行这样的舍入。不过,如果想用2位数字表示99,就容易多了:


在这种情况下,toPrecision(3)等价于toFixed(1),输出的是"99.0"。

toFixed()、toExponential()和toPrecision()方法都会进行舍入操作,以便用正确的小数位数正确地表示一个数。

注意:与Boolean对象相似,Number对象也很重要,不过应该少用这种对象,以避免发生潜在的问题。只要可能,都使用数字的原始表示法。


8 String类
String类是String原始类型的对象表示法,

String对象的valueOf()方法和toString()方法都会返回String型的原始值:

String类具有属性length,它是字符串中的字符个数

两个方法charAt()和charCodeAt()访问的是字符串中的单个字符
charAt()方法返回的是包含指定位置处的字符的字符串:
charCodeAt():如果想得到的不是字符,而是字符代码

concat()方法,用于把一个或多个字符串连接到String对象的原始值上。该方法返回的是String原始值,保持原始的String对象不变:

indexOf()和lastIndexOf()方法返回的都是指定的子串在另一个字符串中的位置(或-1,如果没找到这个子串)。
这两个方法的不同之处在于,
indexOf()方法是从字符串的开头(位置0)开始检索子串,
而lastIndexOf()则是从字符串的结尾开始检索子串的。

localeCompare(),对字符串值进行排序。该方法有一个参数——要进行比较的字符串,返回的是下列3个值之一:

如果String对象按照字母顺序排在参数中的字符串之前,返回负数(最常见的是-1,不过真正返回的值是由实现决定的)。

如果String对象等于参数中的字符串,返回0。

如果String对象按照字母顺序排在参数中的字符串之后,返回正数(最常见的是1,不过同样,真正返回的值是由实现决定的)。

slice()和substring()方法都不改变String对象自身的值。它们只返回原始的String值,保持String对象不变。
对于负数参数,slice()方法会用字符串的长度加上参数,substring()方法则将其作为0处理(也就是说将忽略它)

使用参数3和-4时,差别也很明显。slice()方法将被转换成slice(3,7)
而substring()方法则将这两个参数解释为substring(3,0),实际上即substring(0,3)

toLower- Case()、toLocaleLowerCase()、toUpperCase()和toLocaleUpperCase()。

前两种方法用于把字符串转换成全小写的,后两种方法用于把字符串转换成全大写的。

toLowerCase()和toUpperCase()方法是原始的,是以java.lang.String中的相同方法为原型实现的。

toLocaleLowerCase()和toLocaleUpperCase()方法是基于特定的区域实现的(与localeCompare()的用法相同)。

一般说来,如果不知道在以哪种编码运行一种语言,则使用区域特定的方法比较安全。

记住,String类的所有属性和方法都可应用于String原始值上,因为它们是伪对象。


9 instanceof运算符

在使用typeof运算符时采用引用类型存储值会出现一个问题,无论引用的是什么类型的对象,它都返回"object"。
ECMAScript引入了另一个Java运算符instanceof来解决这个问题。

instanceof运算符与typeof运算符相似,用于识别正在处理的对象的类型。
与typeof方法不同的是,instanceof方法要求开发者明确地确认对象为某特定类型。例如:

var oStringObject = new String("hello world");
alert(oStringObject instanceof String);
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值