函数
定义函数
- 创建一个函数需要用到关键字function,后面是一个函数名
- 为函数提供0或多个参数,使用参数向函数传值
- 可以返回一个值作为调用这个函数的结果,这是可选的
- 编写函数体,包含完成函数工作的所有代码
JavaScript有两种方式定义函数,第一种方式如下:
|
|
注意,函数体内部的语句在执行时,一旦执行到return时,函数就执行完毕,并将结果返回。因此,函数内部通过运算可以实现非常复杂的逻辑。如果没有return语句,函数执行完毕后也会返回结果,只是结果为undefined。
由于JavaScript函数也是一个对象,上述定义的add()函数实际上是一个函数对象,而函数名add可以视为指向该函数的变量。
因此,第二种定义函数的方式如下:
|
|
这种方式下,function{....}
是一个匿名函数,它没有函数名,但是这个匿名函数赋值给了变量add,所有通过变量add就可以调用该函数。
上述两种定义是等价的,注意第二种方式按照完整语法需要在末尾加一个;号,表示赋值语句结束。
函数声明可以出现在脚本中的任何位置。使用多个外部JavaScript文件时有一点要记住,如果不同文件中有两个同名的函数,将使用浏览器最后看到的那个函数。
调用函数
调用函数时,按顺序传入参数即可:
|
|
由于JavaScript允许任意参数而不影响调用,因此传入的参数比定义的参数多也没有问题,虽然函数内部并不需要这些参数:
|
|
传入的参数比定义的少也没有问题:
|
|
此时,add的参数将受到undefined,计算结果为NaN
变量作用域
全局变量
如果一个变量在函数外声明,这个变量就是全局变量。可以在JavaScript代码中的任何地方访问。
|
|
局部变量
如果一个变量在函数内声明,这个变量就是局部变量。只能在函数体内部使用。
|
|
变量提升
JavaScript函数定义有个特点,它会先扫描整个函数体的语句,把所有声明的变量提升到函数顶部
|
|
虽然是strict模式,但语句var x = "hello," + y
并不报错,原因是变量y在稍后说明了。但是alert显示hello,undefined,说明变量y的值为undefined。这正是因为JavaScript引擎自动提升了变量y的声明,但不会提升变量y的赋值。
|
|
由于JavaScript的这一特性,我们在函数内部定义变量时,请严格遵守“在函数内部首先声明所有变量”这一规则。最常见的做法是用一个var声明函数内部所用到的变量:
|
|
对象
普通创建对象
创建对象
已经有了一个包含一些属性的对象。如何使用JavaScript创建这个对象呢?方法如下:
|
|
访问和操作对象
- 使用“点”记法访问对象属性
|
|
- 使用一个串结合[]记法访问属性
|
|
- 改变属性的值
|
|
- 枚举对象的所有属性
|
|
- 处理对象的数组
|
|
- 向函数传入一个对象
|
|
注意:将一个对象赋值给变量时,这个变量会包含这个对象的一个引用,而不是对象的副本,可以把引用想成是对象的一个指针。所有对该变量中属性的改变都会改变原对象的属性。
上述代码中,改变dog对象的weight属性时,实际上是修改的原对象fido的属性,而不是副本,所有不仅函数体内的dog对象发生了改变,函数体外的fido对象也发生了改变。
给对象增加方法
|
|
构造函数创建对象
构造函数
|
|
创建对象
|
|
prototype属性创建对象
prototype属性包含一个对象,所有实例对象需要共享的属性和方法,都放在这个对象里面;那些不需要共享的属性和方法,就放在构造函数里面。
实例对象一旦创建,将自动引用prototype对象的属性和方法。也就是说,实例对象的属性和方法分为两种,一种是本地的,一种是引用的:
|
|
现在,species属性放在prototype对象中,两个实例对象共享的,只要修改了prototype对象,就会同时影响到两个实例对象。
|
|
综上所述,由于所有实例对象共享同一个prototype对象,那么在外界看起来,prototype对象就好像是实例对象的原型,而实例对象则好像继承了prototype对象一样。