自定义Javascript的Apply和Call方法
Liber 2014-04-26 00:43
前几天被问到Apply和Call方法的应用场景,稀里糊涂的乱答一气。
接着又被问到它们的原理,直接语塞。
好在,求知欲还没有彻底沦陷,终于给了自己一个满意的答案:
// Custom the Javascript Apply & Call method.
Function.prototype.customApply = function(obj) {
obj.constructor.prototype['_temp'] = this;
var argStr = '';
if(arguments[1]) {
for(var i = 0; i < arguments[1].length; i++) {
argStr += ',arguments[1]['+i+']';
}
argStr = argStr.slice(1); // Use slice(1) to remove the first ','
}
var functionStr = 'obj._temp('+argStr+')';
var re = eval(functionStr);
delete obj.constructor.prototype._temp;
return re;
}
Function.prototype.customCall = function(obj) {
return this.customApply(obj, Array.prototype.slice.customApply(arguments, [1]));
}
function Cat() {
this.food = 'fish';
}
Cat.prototype = {
say: function(param1, param2) {
console.log('I Love ' + this.food + ', ' + param1 + ', ' + param2);
}
}
var blackCat = new Cat();
blackCat.say('smallFish', 'bigFish');
// Demo use.
var whiteDog = {food: 'bone'};
Cat.prototype.say.customApply(whiteDog, ['Bone!', 'BONE!!!']);
Cat.prototype.say.customCall(whiteDog, 'smallBone', 'bigBone');
// Unit test maybe.
function test() {
var t = Array.prototype.slice.customCall(arguments, 1);
console.log(t);
}
test(1, 2, 3);
复制粘贴以上代码到控制台即可。
原理:
主要看customApply这个里面的这句:
obj.constructor.prototype['_temp'] = this;
首先,这个方法是被say
这个方法调用的,而我们知道,每个function
实际上都是Function
的一个实例,是一个对象。
所以,这里的this
实际上就是那个say
方法。
这句代码先是为传进来的obj
对象的prototype
对象新增了一个_temp
的属性,然后将say
方法赋值给它。
简单的讲,就相当于为obj
对象添加了一个say
方法。
就这样obj
对象就可以调用say
方法了,达到了我们的目的。
原理就是这样,其他的一些代码是处理别的事情,跟原理没什么关系,就不多说了。
不知道Javascript源码是用什么原理实现apply
和call
的,我下载了Chrome V8
的源码,是C
写的,看了以后头更大了……