还有一种情况。我们一开始就说了 JavaScript 是一门弱类型语言,其实不仅仅是弱类型,它的传参数也非常不严谨。你可以多传或者少传(只要保证你多传或者少传的时候可以保证程序不出错,或者逻辑不出错),原则上都是可以的。多传的参数会被自动忽略,而少传的参数会以 undefined 补足。
看看下面的代码就明白了:
javascript
复制代码 代码如下:
// 上接代码2.1
var bar1 = new foo();
var bar2 = new foo("蛋花汤");
请自行输出一下两个 bar 的 hello 变量,会发现一个是 world 一个是 蛋花汤。显而易见,我们的第一个 bar1 在声明的时候,被 Node.js 自动看成了:
javascript
复制代码 代码如下:
var bar1 = new foo(undefined);
所以就有了它是 world 一说。
还有就是在这个构造函数中,我们看到了传进去的参数是 hello 而这个类中本来就有个成员变量就是 this.hello。不过我们之前说过了有 this 和没 this 的时候作用域不同,那个参数只是作用于构造函数中,而加了 this 的那个则是成员变量。用一个 this 就马上区分开来他们了,所以即使同名也没关系。
成员函数
成员函数声明
成员函数的声明跟成员变量的第二种声明方法差不多,即 <类名>.prototype.<函数名> = <函数>;
javascript
复制代码 代码如下:
// 上接代码2.1
function setHello(hello) {
this.hello = hello;
}
foo.prototype.setHello = setHello;
bar1.setHello("鸡蛋饼");
上面这段代码显而易见,我们实现了 foo 类的 setHello 函数,能通过它修改 foo.hello 的值。
但是这么写是不是有点麻烦?接下去我要讲一个 JavaScript 函数重要的特性了。
★ 匿名函数 ★
很多时候我们的某些函数只在一个地方被引用或者调用,那么我们为这个函数起一个名字就太不值了,没必要,所以我们可以临时写好这个函数,直接让引用它的人引用它,调用它的人调用它。所以函数可以省略函数名,如:
javascript
复制代码 代码如下:
function(hello) {
this.hello = hello;
}
至于怎么引用或者调用呢?如果是上面的那个类需要引用的话,就是写成这样的:
javascript
复制代码 代码如下:
foo.prototype.setHello = function(hello) {
this.hello = hello;
}
这样的写法跟 成员函数 声明 是一个效果的,而且省了很多的代码量。而且实际上,基本上的类成员函数的声明都是采用这种匿名函数的方式来声明的。
至于说怎么样让匿名函数被调用呢?这通常用于传入一个只被某个函数调用的函数时这样写。
比如我们有一个函数的原型是:
javascript
复制代码 代码如下:
/**
* 我们将传入a,b两个变量,
* 在算出a+b的值后,交由func(num)
* 去进行输出
*/
function sumab(a, b, func) {
var c = a + b;
func(a, b, c);
}
比如我们有两个版本的输出函数,一个是中文输出,一个是英文输出,那么如果不用匿名函数时候是这么写的:
javascript
复制代码 代码如下:
function zh(a, b, sum) {
console.log(a + " + " + b + " 的值是:" + sum);
}
function en(a, b, sum) {
console.log(a + " plus " + b + " is " + sum);
}
sumab(1, 2, zh);
sumab(3, 4, en);
执行一遍这段代码,输出的结果将会是:
1 + 2 的值是:3
3 plus 4 is 7
这样的代码如果采用匿名函数的形式则将会是:
javascript
复制代码 代码如下:
sumab(1, 2, function(a, b, sum) {
console.log(a + " + " + b + " 的值是:" + sum);
});
sumab(3, 4, function(a, b, sum) {
console.log(a + " plus " + b + " is " + sum);
});
这种形式通常使用于回调函数。回调机制算是 Node.js 或者说 JavaScript 的精髓。在以后的篇章会做介绍。
成员函数声明的匿名函数声明方式
虽然上一节讲过了,不过还是再讲一遍吧。