理解JavaScript的call和apply使用情景的最简单直观的例子

/*
业务逻辑:
1、如果person见到person,ET见到ET,则相互sayHi;
2、如果person见到ET,则逃跑;
3、如果ET见到person,则吃掉;
ps: 举个这样蹩脚的例子,是想说明:call非常适合用在这种需要解耦代码的情况中,避免同样代码再写一次。
*/

//这个person对象有一个sayHi和run 逃跑方法
function Person(name){ 
   this.type="person";
   this.level = 1;
   this.name=name;
};

Person.prototype={
   sayHi:function(obj){console.log("hi! "+obj.name)},
   run:function(obj){console.log("run! It's " + obj.type)}
}

//这个ET(外星人)对象也有一个sayHi方法,不过肯定是用外星语打招呼,还有一个把人吃掉的eat方法
function ET(name){ 
   this.type="ET";
   this.level = 2;
   this.name=name;
};

ET.prototype = {
   sayHi:function(obj){console.log("ET language say hi to "+obj.name)},
   eat:function(obj){console.log("eating a person! named "+ obj.name)}
};

/*
这个someMethod前面加个window,只是为了显式说明someMethod是一个window对象的方法。
它是游戏主控逻辑中的情节判断逻辑,是person对象 和 ET对象 都需要的一段代码,通过使用call可以把它解耦出来。
如果日常工作的业务逻辑中有这种类似的情况,我们可以使用call来解耦。
*/ window.someMethod = function(obj){ if(this.type === obj.type) { this.sayHi(obj); }else{ if(this.level < obj.level){ this.run(obj); }else{ this.type==="ET" ? this.eat(obj) : this.sayHi(obj); } } } var ps_macliu = new Person("macliu"); var ps_tony = new Person("tony"); var et_1 = new ET("ET1"); var et_2 = new ET("ET2"); //人类遇到人类 someMethod.call(ps_macliu, ps_tony); // hi! tony //人类遇到外星人 someMethod.call(ps_macliu, et_1); // run! It's ET //外星人遇到人类 someMethod.call(et_1, ps_macliu); // eating a person! named macliu //外星人遇到外星人 someMethod.call(et_1, et_2); // ET language say hi to ET2