ppk on javascript 笔记(五)

第5章 核心

1999年ECMA将核心标准化为ecmascript(http://www.ecma-international.org/publications/standards/Ecma-262.htm),对该规范最重要的评论来自Douglas Crockford(http://crockford.com/javascript/recommend.html)关于Crockford更多的文章可参考(http://dancewithnet.com/2009/03/29/douglas-crockford/

 

基础知识

区分大小写

语句和分号:分号表示一条语句结束;对于一行代码的语句,不管是否以分号结尾,javascript会自动插入分号;当使用if,for或while控制结构时,可以不用分号结束。

注释

代码块:{};当if, while, for只包含一条语句时,可以省略{};函数主体必须在{}中。

运算符:优先级;返回值;赋值运算符返回当前的值,因此可以使用var a=b=1;

值:函数也可以用来赋值(注意使用为值时不应该再带括号)。

 

数据类型

javascript有4种重要的数据类型:数字、字符串、布尔型和对象;4种小数据类型:undefined、null以及表示“不存在”的两种说法。

null意味着无值,下面不会报错,显示为null,但当我们使用null值时就会报错--缺少对象。

var x = document.getElementById('test');
alert(x);

undefined发生在3种情况:声明了一个变量,但没有赋值;访问一个对象尚未声明的属性;定义了函数的参数,但没有传值给它。

alert(y);
var x; alert(x);
alert(window.y);

第一条语句会报错:y未定义;第二行和第三行则会显示undefined。

typeof运算符表示一个值的数据类型,它有两个特例:

var x =1; alert(typeof x);
var y ='1'; alert(typeof y);
var z =true; alert(typeof z);
function f() {}
alert(
typeof(f));
alert(
typeof(null));

第一行返回number,第二行返回string,第三行返回boolean。 

函数使用typeof时返回function,null则返回object。

数据类型转换:javascript会根据需要将一种类型解释为另一种类型,原类型并没有改变。如:

var a = 2;
var b ='3';
var c = a * b;

a是一个数字,b是一个字符串,在做乘法运算时,将b解释为数字,结果c是一个数字,值为6,b并没有改变,仍是一个字符串。

上面的alert(x),实际上也是把null解释为字符串,然后输出。

当字符串不能被解释为数字时,返回NaN.

使用+时,总是解释为连接,而不是加法运算。

转换为布尔型时,null, undefine, 数字0, NaN, 空字符串''被转换为false,其他所有的值被转换为true。

显式的数据类型转换,如:x1或者-0将字符串转换成数字,+''将转换成字符串,使用!!转换成布尔型。

 

普通运算符

* - / %及*=等,++和--同样区分前后,=赋值运算符返回被赋予的值,==相等运算符,===等同运算符要求数据类型一致,同样!==不等同运算符也针对数据类型。

比较运算符总是先将变量解释为数字进行比较,若有一个不能解释为数字,则按照第一个字母顺序进行比较,后面的大于前面的,小写的大于大写的(类似ascii)

条件运算符?:

 

变量

变量命名习惯采用低驼峰命名规则(lowerCamelCase),W3CDOM也如此命名,命名时不要使用保留字。

允许对一个未声明的变量直接赋值,这个变量会自动声明,但不允许直接使用未声明的变量,最好使用var显示声明以保持代码清晰。

按作用域分为全局变量和局部变量,没有块作用域,当在函数体中用var显式声明或作为函数的参数时为局部变量,其他情况如在函数体内未用var声明而直接使用或在函数体外声明的都是全局变量,尽量使用局部变量。

 

处理数字

不区分整数和浮点数,在使用浮点数时会产生舍入误差的bug,因此浮点数运算的结果在显示之前要先进行舍入。0.5可以简写为.5s

以0开头的数字为8进制,以0x开头的数字为16进制。

Math对象:

取整的三种方法:Math.round(), Math.floor(), Math.ceil(),同样适用于负数;

Math.random()用于产生0~1的随机数;

Math.abs()取绝对值。

n.toFixed(2)将数字n转换成一个拥有固定位数的字符串,要求n必须为number类型,否则会报错;它返回字符串。

全局方法parseInt(x)和parseFloat(x)将字符串转换为数字,它逐字符检查字符串,直接遇见非数字字符为止,当第一个字符非数字时才返回NaN,而上面的显式转换则要求字符串必须全部为数字,(注意16进制的x和float的.也是允许的)。

 

与字符串打交道

习惯上适用单引号表示字符串,允许使用双引号,\为转义符,+为连接符。

x.length用于取字符串的长度,这是字符串对象的一个属性,且是只读的。

x.indexOf('a')和x.lastIndexOf('a')用于检索,它返回的索引从0开始,未检索到时返回-1,可以指定检索开始的位置,如x.indexOf('a', 2), x.lastIndexOf('a', x.length-1)。

x.charAt(9)返回指定位置的字符,索引从0开始。

x.substring(9)或x.substring(9, 11)返回开始位置和结束位置之间的字符串,索引从0开始。

x.split('c')用指定的分隔符将字符串转换为数组,分隔符本身并不出现。

x.toLowerCase()和x.toUpperCase()用于大小写转换。

 

处理布尔值

布尔型数据只有两个:true和false。

逻辑运算符|| && !,注意javascript也包含逐位运算符&和|。

if(!document.styleSheets)对象检测时,若浏览器不支持这种方法,即为一个不存在的对象null,它被转换为false。

逻辑运算符||和&&并不返回布尔值,而是返回运算中最后一次计算的表达式的值。

例如,应用这个方法,我们可以使用来取得事件目标

var evtTarget = evt.target || evt.srcElemnt;

大多数的浏览器将事件目标保存在evt.target中,而IE保存在srcElement中,当evt.target非null时,则返回,否则继续计算srcElement。&&用法也如此。

 

控制结构

if ... else if ... else ...

switch(...) { case ..: .. break; default:... } 注意,switch允许任意的数据类型(其他语言如java只允许对数字),但switch与case比较时,不会进行数据类型的转换。

四种循环语句:for, while, do/while, for in

for, while 条件检测总在循环体执行之前,而do/while先执行后检测。

当while陷入无限循环时,浏览器会提示是否终止代码运行。

do { ...} while(..); 最好在do/while的最后加一个分号。

break与continue。

当在嵌套循环中想跳出外层循环时,使用标签是可行的,事实上,任何语句都可以标志为标签。

myloop:for(var i=0; i<x.length; i++) {
for(var j=0; j<x.length; j++) {
if([something is the case]) continue myloop;
}
}

try/catch用来确保用户不会看到错误信息。

 

函数

定义一个函数 function f() {} 或 var f = function() {}。

函数可以直接return;或return任意一个数据类型。

var g=f; 则定义了函数的一个引用,可以运行g();。

当将函数作为一个值时不能使用(),而()运算符则命令函数执行。

函数可以内嵌函数,使用内嵌函数时,需注意局部变量的作用域:

function init() {
var message =' clicked ';
var x = document.getElementsByTagName('a');
for (var i=0; i<x.length; i++) {
x[i].onclick
=function() {
x[i].firstChild.nodeValue
= message;
}
}
}

函数运行在被定义的作用域中,而不是执行它们的作用域中。这意味着内嵌函数可以访问所有它的父函数的局部变量,即使父函数在内嵌函数调用前就早已执行。

在此,内嵌函数访问了父函数的局部变量i和x,但是i发生了错误,程序报错。这是因为内嵌函数只能访问到局部变量的最终值;

假设x.length=9,那么init函数执行结束后i的值为10,以后当内嵌函数触发时就会使用这个i,于是使用了x[10]这个null值,从而报错;

正确的写法应该是 x[i].onclick = function() { this.firstchild.nodeValue = message; }

 

对象

对象用来保存彼此相关联的变量和函数,也就是一组属性的集合,值为函数的属性称作方法,点运算符用来获取一个属性或方法。

允许自定义对象 var t = new Object(); t.a = 1; t.b = function() {}

可以用字面量来定义对象 var t = { a:1, b:fucntion() {} }属性间用逗号隔开。

访问一个属性没有什么害处,不管对象是否有这个属性,但是访问一个方法的同时也尝试去执行它,例如

function stopProp(e) {
if(e.stopPropagation) {
e.stopPropagation();
}
e.cancelBubble
=true;
}

对停止事件传播,W3C标准的浏览器需执行stopPropagation方法,而IE只需将cancelBubble设为true,上面这种写法是规范的,直接访问不存在的方法会报错,而对于W3C标准的浏览器则只是多创建一个值为true的属性而已,但是这个属性对IE来说却是一个预定义属性,改变预定义属性的值便会引起一些相应的动作。

允许创建自己的属性。

this关键字出现在方法中(js不区分方法和函数),用来引用定义该方法的对象。

属性和变量也是对等不区分的,全局变量也即全局对象window的属性。

 

关联数组

下面两种表达式等价的:object.property; object['property']; 同样的这也是等价的:object.method(); object['method']();

使用点符号时,后面的属性名或方法名是固定的字符串常量,而使用方括号则可以使用变量随意更改属性的名字。

关联数组是一个数组,它允许通过字符串作为值的名字来找到某一个确定的值,这些字符串叫做关键字。

for in用来遍历一个关联数组,例如

var t = {
a:
2,
b:
'2',
c:
function() {
alert(
this.a*this.b);
}
}
for(var i in t) {
alert(i
+':'+ t[i]);
}

弹出的三个信息分别为a:2,b:2和c:fuction() { alert(this.a*this.b); }。注意到i表示了关键字,而方括号使用了变量i来获取t的属性(点符号是行不通的,t.i表示t的i属性),同时也可以看到a的值数字2被转换成了字符串2。

 

数组

数组是一个用数字来索引的值的集合,索引数从0开始,例如

var t =new Array();
t[
0] ='2';
t[
2] =3;
t[
5] =function() {
alert(
this[0] *this[2]);
}
t[7] = new Array();
t[7][5] = false;
t[
5]();
alert(t[
1]);

这定义了一个稀疏数组,它只定义了几个元素,对于其他元素根本就没有创建它们,访问时会返回undefined,就好像一个未定义的属性一样。运行t[5]()会弹出6。t[7]则是一个嵌套数组。

除了上述定义方法,数组还有两种表示法:

var s =new Array(0, 1, '2', 'three', false);
var t = [0, 1, '2', 'three', false];

这两种方法无法指定特定的索引序列,其中后一种方法数组字面量常用。

如getElementsByTagName获得的节点列表并不是数组,可以看做为缺乏所有定义在数组对象上的有用方法的只读数组,以后再介绍。

length属性表示数组长度,数组长度总是最大的索引数加1,包括稀疏数组。增加减少元素会更新length的值,对length属性赋值会改变数组,访问超出长度的索引会返回undefined。

设t是一个数组,有四种方法增减元素:t.unshift(x);用来插入一个起始元素,t.shift();删除一个起始元素,t.push(x)插入一个末尾元素,t.pop()删除一个末尾元素。

 

posted @ 2010-07-30 00:12  bloodmage  阅读(388)  评论(0编辑  收藏  举报