http://rolfzhang.com/articles/191.html
JavaScript小特性(7)——面向对象http://rolfzhang.com/articles/825.html
其他所有 http://rolfzhang.com/?s=JavaScript%E5%B0%8F%E7%89%B9%E6%80%A7
最近看完了《ppk on JavaScript》,一本算是进阶的JavaScript基础书,讲了很多不看书发现不了的小细节,但是都是些很重要的细节,例如事件处理,浏览器兼容等等。
本来打算看O’Reilly的《JavaScript权威指南》(好像是厚厚一大本)巩固一下基础,网易面试那个考官给我推荐的,去图书馆找不着,应该被借了。碰巧发现这本《ppk》,图灵出版,淘宝UED译,应该差不到哪去,就借回去了(而且比较薄,我喜欢薄滴~ )。
下面我就讲些看书中遇到的一些要注意的地方:
1、数据类型转换
JavaScript总的来说只有4种数据类型:number、string、boolean、对象(如果算上undefined和null就6种,NaN是number类型)。
JavaScript是弱变量类型的,一个变量可以存放任意数据类型,而且数据类型可以自动互相转化(这东西看起来方便,却是万恶的根源呀~~)。
1
2
3
4
5
6
7
8
|
var
a =
'5'
//a为string
var
b = a * 2;
//string与number相乘,b数字
var
c = a + b;
//因为a是string,表达式变为string
c =
new
Object();
//c被赋值为一个object
if
(a && b && c){
//number、string、object自动转为boolean
//null、undefined、零、NaN都转为false,其他转为true
//do something
}
|
问题容易出在哪呢?最常见的就是‘+(加号)’既是加法运算符,又是字符串连接符,导致数字运算经常不知怎么的变成了字符串连接。
介绍几种强制数据类型转换的方法:
- ” + a -> string
- a * 1 -> number //如果不能正确转换,则为NaN(not a number)
- !!a -> bool
- a.toFixed(num) -> string //转为固定小数位数的字符串(a为number类型)
2011/5/20修订:
+a -> number //同 a*1,此处的“+”是正号的意思
其实,JavaScript有自带的强制转换方法,不过我觉得上面的要方便些
- Boolean(value) – 把给定的值转换成 Boolean 型;
- Number(value) – 把给定的值转换成数字(可以是整数或浮点数);
- String(value) – 把给定的值转换成字符串;
顺带说一下浮点数转为整数的几个方法(js的数字类型是不分浮点数与整数的):
- Math.round(num);//四舍五入
- Math.floor(num);//向下取整
- Math.ceil(num);//向上取整
2、特殊返回值
JavaScript 的布尔运算 &&、|| 是有返回值的,但不是boolean值,而是该布尔运算计算的最后一个表达式的值。
1
2
3
4
5
6
|
var
x =
'JavaScript很诡异'
;
var
y =
'Java很繁琐'
;
alert(x || y);
//输出:JavaScript很诡异,x转换为true,不继续运算,返回x
alert(x && y);
//输出:Java很繁琐,x转为true,继续运算,返回y
|
这种特性常用于检测某对象是否存在(虽然&&也可以用来做对象检测,但我们一般不这样做)
1
2
3
4
5
|
function
eventHandler(e){
//某注册事件的处理函数
var
evt = e || window.event;
//获得事件对象,W3C和微软的获取方法不同
vat evtTarget = evt.target || evt.srcElement;
//获取事件目标对象
//do something
}
|
另外js里面,=(等号) 也是有返回值的,即可以连续赋值,如:
window.jQuery = window.$ = jQuery
3、控制结构
JavaScript支持所有常用的控制结构(这是必须的嘛),如if/else if/else,while/do while,for,continue/break,try/catch/finally …
还有一种for in结构
1
2
3
4
5
6
7
8
9
|
var
test = {
a:
'1'
,
b:2,
c:
function
(){alert(3)}
}
for
(
var
i
in
test){
alert(
typeof
test[i]);
//此处的i是对象的属性名
//如果是数组,则是数组的索引
}
|
它还支持使用标签做控制结构,如
1
2
3
4
5
6
7
8
9
10
|
outerloop:
for
(;;){
for
(;;){
if
(
true
){
alert(
'innerloop'
);
break
outerloop;
//直接跳出外层循环
}
}
}
alert(
'outerloop'
);
|
顺便说一个for循环和try/catch结合,解决浏览器工作环境依赖的例子:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
|
function
createXMLHttpObject(){
var
xmlhttp =
false
;
for
(
var
i=0,len=XMLHttpFactories.length;i<len;i++){
try
{
xmlhttp = XMLHttpFactories[i]();
}cateh(e){
//如果产生异常就试下一个
continue
;
}
break
;
//找到就跳出循环
}
return
xmlhttp;
}
//此数组包含创建XMLHTTP对象的所有可能方式
var
XMLHttpFactories = [
function
(){
return
new
XMLHttpRequest()},
function
(){
return
new
ActiveXObject(
'Msxml2.XMLHTTP'
)},
function
(){
return
new
ActiveXObject(
'Msxml3.XMLHTTP'
)},
function
(){
return
new
ActiveXObject(
'Microsoft.XMLHTTP'
)}
];
|
4、对象/数组
对象和数组为啥要放在一起讲呢,因为我觉得他们在很多地方非常相似,我觉得数组可以算是一种简化版的对象吧(当然数组和对象从本质上还是很大不同的)。
先说几点关于对象和数组的重要的杂事~
- a、一个数组可以保存多个数据类型,如var arr = [1,'a',true,function(){alert('a')}];//包括对象、函数、嵌套的数组
- b、所有的全局变量都包含于一个全局对象window,也就是说 var a = 2 等同于 window.a = 2;//所以说,JavaScript其实是面向对象的,神马都与对象有关~
- c、所有函数都是一个Function对象(既然是对象,你就可以给他附上各种属性,各种js库就是这样弄出来的),可以通过new FunctionName()的方法来创建新对象;
- d、‘.(点)’是用于访问对象的属性或方法的,如test.a、test.method(),我们也可以这样:test['a']、test['method'](),两种方法等价。后一种访问方式有点像Map,可以当做key/value结构使用;
下面说说对象和数组的字面量,也就是用一个字符串代替对象或者数组的创建(便于信息的传输):
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
//标准对象创建方法
var
test =
new
Object();
test.a = 100;
test.b =
'100'
;
test.c =
function
(){alert(test.a*test.b);}
//对象字面量(也就是大名鼎鼎的JSON格式啦~~)
var
test = {
a: 100,
//属性名:属性值,结尾有,(逗号)
b:
'100'
,
c:
function
(){alert(test.a*test.b);}
//最后一个无,(逗号)
}
//标准数组创建方法
var
arr =
new
Array(1,2,3,4,5);
//几乎没人用这种方法吧~
//数组字面量
var
arr = [1,2,3,4,5];
//这种简单多了
|
5、函数
(此节新增于2011/5/20)
JavaScript里面,所有的函数都是一个对象。我们可以这样创建一个函数:
1
2
|
var
sayHello =
new
Function(
"toWho"
,
"alert(\"hello \"+toWho+\"!\")"
);
sayHello(
"world"
);
|
Function对象的构造方法如下(前面的参数是函数接受的参数,最后一是函数体本身,全部都是字符串形式):
1
|
var
myfun =
new
function
(arg1, arg2, ..., argN, function_body)
|
Function对象里面有一个特殊的属性,arguments对象,里面包含了函数调用时传入的所有参数
1
2
3
4
5
|
function
testArguments(){
for
(
var
i
in
arguments){
alert(
"arguments["
+i+
"] : "
+arguments[i]);
}
}
|
既然所有的function都是一个对象,那么函数名就是指向这一对象的引用,我们可以将一个函数赋值给多个引用
var myfun = function(){
1
2
3
4
5
6
|
alert(
'这是一个函数'
);
}
var
myfun2 = myfun;
myfun();
myfun2();
|
那么问题又来了,既然函数名是一个引用,那么一个引用当然不能指向多个对象,导致JavaScript并不支持函数重载。
虽然函数重载似乎对JavaScript并不是这么重要,但如果真要使用,可以考虑用arguments对象进行模拟函数重载,例如:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
function
add(){
if
(arguments.length == 1){
return
arguments[0]+1;
//自增
}
else
if
(arguments.length > 1){
var
sum = 0;
for
(
var
i
in
arguments){
sum+=arguments[i];
//求和
}
return
sum;
}
return
0;
}
alert(add(1));
alert(add(1,2,3));
|
JavaScript函数还有一个闭包的特性,欲知详情,请看这里,和这里。
这篇就先说这么多,下回讲讲BOM、DOM相关的东西,例如事件处理、DOM修改神马的~~~