数字营销 · Web开发 · 基础设施

JavaScript和PHP中对调用对象的类型控制

通过妻子、丈夫和银行的例子,对比 PHP 与 JavaScript 中对象参数的类型控制方式。

在 PHP 中,有这样三个类:妻子、丈夫和银行。

妻子和丈夫各有三个属性,分别是性别、拥有的钱,以及各自不同的方法。

妻子的方法是每个月把丈夫挣到的钱收起来,丈夫则每个月把钱交给妻子。

剩下的一个银行类,有一个资产属性和一个交钱的方法,不过这里的“交钱”只是为了方便演示类型控制。

在 PHP 中,我们可以这样定义这三个类:

<?php

class Wife{
public $sex="female";
public $money=10000;

public function savemoney($people){
$this->money += $people->handed(1000);
}
}

class Husband{
public $sex="male";
public $money=10000;

public function handed($num){
$this->money -= $num;
return $num;
}
}

class Bank{
public $money=100000000;

public function handed($num){
$this->money -=$num;
return $num;
}
}

我们知道,丈夫的钱上交给妻子,这是理所当然的。

但是,上面的程序存在一个问题:银行的钱也可以交给妻子。

<?php

$she=new Wife();
$he=new Husband();
$ccb=new Bank();

$she->savemoney($he);

echo $she->money, "<br/>";
echo $he->money;

// 接下来看看妻子能不能接受银行的上交
$she->savemoney($ccb);

echo $she->money;
echo $ccb->money;

这样的话,妻子俨然成了“抢劫犯”。

显然,这在实际程序中是不合理的。

那么,如何阻止这种情况发生呢?

PHP中的类型控制

PHP 提供了类型声明,我们可以在 savemoney() 方法的参数中指定接收的对象必须是 Husband 类型:

class Wife{
public $sex = "female";
public $money = 10000;

public function savemoney(Husband $people){
$this->money += $people->handed(1000);
}
}

这样,当再次执行 $she->savemoney($ccb);

PHP 就会提示参数类型错误,因为这里传入的是 Bank 对象,而方法要求的是 Husband 对象。

这样,就可以很好地解决参数类型的问题。


JavaScript中怎么做?

那么在 JavaScript 中,如果也想做类似的控制,应该怎么办?

先看一下没有进行类型判断时的代码。

functionWife(){
this.sex ="female";
this.money =10000;

this.savemoney =function(people){
this.money +=people.handed(1000);
};
}

function Husband(){
this.money =10000;
this.sex ="male";

this.handed =function(num){
this.money -=num;
return num;
};
}

functionBank(){
this.money =100000000;

this.handed =function(num){
this.money -=num;
return num;
};
}

var she=newWife();
var he=newHusband();
var ccb=newBank();

she.savemoney(he);

console.log(she.money);
console.log(he.money);

she.savemoney(ccb);

console.log(she.money);
console.log(ccb.money);

可以看到,在这个例子中 she.savemoney(he) 能够正常执行。

但是 she.savemoney(ccb) 同样也能够执行。

因为 JavaScript 不会像 PHP 一样,在这里直接声明:

savemoney() 必须接收一个 Husband 对象。

那么,这时候应该怎么做?

其实很简单,我们只需要判断传入的对象是不是 Husband 的实例即可。

JavaScript 提供了 instanceof 运算符,可以用来判断一个对象的原型链上是否存在指定构造函数的 prototype

使用instanceof进行判断

可以把 Wife 改成:

function Wife(){
this.sex ="female";
this.money =10000;

this.savemoney = function(people){
if(!(peopleinstanceofHusband)){
throw new TypeError(
"Type error: people must be an instance of Husband"
);
}

this.money +=people.handed(1000);
};
}

这样:

var she=newWife();
var he=newHusband();
var ccb=newBank();

she.savemoney(he);

可以正常执行。但是 she.savemoney(ccb) 就会抛出类型错误.

也就是说,我们通过 people instanceof Husband

判断传入的 people 是否是 Husband 的实例。

如果不是,就不允许继续执行。

PHP和JavaScript的区别

通过上面的例子可以看出来,PHP 和 JavaScript 都可以对传入的对象进行一定程度的类型控制,但是实现方式并不一样。

PHP 可以直接在参数中声明:

public function savemoney(Husband $people)

而 JavaScript 则需要在函数内部主动进行判断:

if(!(peopleinstanceofHusband)){
throw new TypeError(...);
}

所以,在 JavaScript 中,如果我们希望一个函数只能接受某一类对象,就可以利用 instanceof 进行判断。

不过需要注意,instanceof 判断的并不是“这个对象里面有没有某几个属性”,而是检查对象的原型链与指定构造函数的 prototype 之间是否存在对应关系。

对于刚开始学习 JavaScript 对象和继承的人来说,理解这一点还是比较重要的。

评论0

欢迎分享你的看法,也欢迎补充不同的实践经验。