引言

      编程世界只存在两种基本元素:一个是数据、另一个是代码。无论多么复杂的程序,都是对数据和代码间千丝万缕的关系进行的操作。

 

 

一、回归简单,JavaScript的数据类型

1.       简单数据类型

1)       undefined:代表一切未知的事物,什么也没有(注意:typeof(undefined)也是undefined)

2)       null:有一个空间,但空间中没有数据

3)       boolean:布尔类型

(1)    undefined,null,’’,0转换为布尔类型,结果都为false,其它一切值转换成布尔类型都为true,例:alert(Boolean(undefined));

(2)     ===:全等,表示类型和值都要相等,例:alert("123"==123);alert("123"===123);

4)       number:数值类型

5)       string:字符串类型

 

 

2.       复杂数据类型,只有object类型

在JavaScript中不要被类所束缚,JavaScript没有类的概念,因为它已将类化为无形与对象溶为一体了,看下面的代码:

var
for(life.age=0; life.age<3; life.age++){
switch(life.age){
case 0:life.body="卵细胞";
life.say=function(){alert("now i'm a "+this.body);}
break;
case 1:life.body="小蝌蚪";
life.tail="尾巴";
life.say=function(){alert("now i'm a "+this.body);}
break;
case 2:life.body="青蛙王子";
delete life.tail;
life.legs="腿";
life.say=function(){alert("now i'm a "+this.body);}
break;
}

life.say();
}

上面可以看到,一个life对象从卵细胞变成小蝌蚪再变成青蛙王子,是多么的有趣,这就是JavaScript的魅力,life不是某个类的固定的实例化对象,它 是如此的灵活,并不局限于某个固定的类;假如我们用面向对象的思想来编写的话,会怎样呢?那么我们就需要建立三个类来反映life生命中的三个阶段,然后再来编程,假如life对象有十个生命过程呢?my god那就要十个对象了,那再多一点~~~~~~,面向对象是为了帮助我们理解问题解决问题的,当它成为了我们的阻碍时,我们就要坚决地抛弃它。

 

 

3.       function,函数,程序之神

1)       静态函数:function xxx(){…},如果在同一个程序段内,出现同名的静态函数,那么该函数将以最后位置的函数为准。例:

<scripttype="text/javascript">
function test(){alert("hello");}
test();
function test(){alert("hi~~~");}
test();
</script>

我们会看到,它两次都弹出hi~~~,即最后位置的函数。

 

 

2)       动态函数:var xxx = function(){…},动态函数不存在静态函数同名的问题,在程序执行到时,最后赋值的函数就是要调用的函数。例:

<script type="text/javascript">
var test = function(){alert("hello");}
test();
var test = function(){alert("hi~~~");}
test();
</script>

这里我们可以看到,程序先弹出hello,后弹出hi~~~,第一个test执行前赋值的是弹出hello的函数,而第二个test执行前赋值的是弹出hi~~~的函数。

 

 

3)       JavaScript是一段段地分析执行函数,而不是一行行地分析执行,如果将上面的静态函数的例子拆成两个程序段,就可以看出来,例:

<scripttype="text/javascript">
function test(){alert("hello");}
test();
</script>
<scripttype="text/javascript">
function test(){alert("hi~~~");}
test();
</script>

可以看到,程序先输出hello后输出hi~~~,证明了JavaScript是一段段的执行的。

一段代码中的静态函数会优先执行,这一特征被称为“JavaScript的预编译”,事实上,JavaScript的预编译还包括对所有var变量的创建(初始值为undefined),用以提高对代码的执行效率。(请注意此段话,后面会有示例)

 

 

二、变量、属性、作用域

1.       任何程序都会在一个原始的环境中开始运行,这个原始的环境被称为“全局环境”,全局环境包含一些预定义的元素,这些元素对于我们的程序来说是自然存在的,我们直接拿来即可用,就像我们呼吸的空气一样。在JavaScript中,这个全局环境就是window对象。

 

 

2.       变量与属性

1)       变量:var myName=”luo”;这里声明了一个变量

2)       属性:myName=”soldierluo”;这里定义了一个属性

 

 

3.       变量的作用域只在函数体内,而属性则没这样的限制,这样的安排是JavaScript的一个极大的特点,请特别注意,例:

<script type="text/javascript">
var firstName = "luo";
var lastName = "jun";
fullName = "soldierluo";
alert("firstName:"+firstName+" lastName:"+lastName+" fullName:"+fullName);
function
alert("firstName:"+firstName+" lastName:"+lastName+" fullName:"+fullName);
var firstName = "soldier";
lastName = "kkk";
fullName = "changed";
alert("firstName:"+firstName+" lastName:"+lastName+" fullName:"+fullName);
}
test();
alert("firstName:"+firstName+" lastName:"+lastName+" fullName:"+fullName);
</script>

上面这个例子非常有意思,程序总共弹出了四次,firstName由luo->undefined->soldier->luo;而lastName为jun->jun->kkk->kkk;fullName则是soldierluo->soldierluo->changed->changed;

看来变量lastName和属性fullName比较像呢!为什么同是变量的firstName反而更不同呢?因为作用域,请看test函数中也声明了一个firstName的变量,这样它就会屏蔽父域中的同名变量,那为什么是undefined呢?看看上面标红的关于JavaScript预编译的那段话就清楚了,此时的firstName被预编译设置成undefined,等到之后赋值为soldier后再输出就是soldier了。最后firstName怎么又变成luo了呢?因为test函数结束后,test函数中的变量就消失了,所以父域的变量又出现了,就这么回事。

至于lastName和fullName,就不需要解释了吧,他们都是正常的作用域内,规规矩矩的变化着。

看了上面的实例,应该比较清楚什么时候用var了吧,如果使用var,那么它就是一个临时变量,函数结束后它就消失了,而全局变量和属性则不会。所以,在函数中尽量使用var可以避免不必要的冲突,比如修改了父域的变量或属性等等。

 

 

4.       caller对象,返回调用该函数的函数,如果为null,则表示被全局函数调用,例:

  

<script type="text/javascript">
function
function
test();
useTest();
</script>

 

5.       arguments对象,函数属性,传入参数的集合,例:

 

<script type="text/javascript">
function
function
test();
test_1();
test_1(1,6);
</script>

可以看到,arguments是实际传入的参数的集合,与函数的定义无关,可以通过arguments[index]来访问参数。

 

 

三、object&function,对象与函数

1.       如果我说函数和对象是一样的,或者说函数就是对象,你一定会骂我sb,对象是实体,函数是行为,怎么可能一样,其实你说的都不错,但是,这是在JavaScript里,事实上函数就是对象。例:

<script type="text/javascript">
function sing(){alert(sing.name+":"+sing.title);}
sing.name = "李白";
sing.title = "《关山月》";
sing();
sing.name = "白居易";
sing.title = "《琵琶行》";
sing();
</script>

可以看到sing作为一个函数,我们却可以直接为它添加属性,这不是对象的基本特征吗?通过上面的例子,我们可以很清楚地看到,在JavaScript中,函数的本质它就是对象,只不过它是特殊的可以被调用的对象。

 

 

2.       放下对象,找到自我

1)       this,就是自我,但是这个自我是谁呢?谁调用了函数,那么这个函数的this就是这个谁谁谁(对象)了。例:

  

<script type="text/javascript">
function whoIam(){alert("i'm "+this.name);}
var luo = {name:"luojun", say:whoIam};
luo.say();
var soldier = {name:"soldierluo", say:whoIam};
soldier.say();
luo.say.call(soldier);
soldier.say.call(luo);
({name:"noName", say:whoIam}).say();
</script>

从这里我们可以看到,谁调用了whoIam,whoIam中的this就是谁,如果是由window对象调用,那么this就是window了。所以这个this是个很油头的东西,有奶便是娘。

 

 

2)       在一般的对象语言中,方法体代码中的this可以省略,因为成员默认都首先是自己的。但JavaScript却不同,由于有奶便是娘的特点,它没有自己,它必须找到一个有奶的娘,它才知道自己是谁,所以如果要访问自己下的属性或方法时,this不能省略。例:

<script type="text/javascript">
name="luo";
function whoIam(){alert("i'm "+this.name+" name:"+name);}
var
soldier.say();
</script>

我们看,soldier对象调用了whoIam函数,此时whoIam中的this就是soldier对象了,而soldier对象没有定义name属性,所以是应该访问不到的,但是如果不用this的话,whoIam函数就是跑到它的祖先域中去查找name属性,这自然不是我们要的结果,因为我们的目的是访问soldier对象的name属性,所以不使用this来访问自己的属性或方法是会出现错误的。

 

 

四、对象素描,json是一种非常简便的创建JavaScript对象的方法

1.       对象属性定义在{}两个大括号之间

2.       属性是以键值对的方式呈现

3.       键值之间用:冒号分隔

4.       键值对之间用,逗号分隔

5.       如果是数组的话,使用[]中括号,值在中括号间

例:  

<script type="text/javascript">
var
name:"microsoft",
say:function(){alert("i'm "+this.name+", most important product is "+ this.products[0]);},
products:["windows","office","xbox"]
};
company.say();
</script>

怎样?很是简洁吧,json是JavaScript对象最好的系列化形式,它比xml更简洁。我们还可以使用eval函数,直接将json转换成一个JavaScript对象,这使得它成了ajax的宠儿。