Function.prototype.call 是 JavaScript 函数原型中的一个函数,它调用函数,使用第一个参数作为 this 参数,并传递剩余参数作为被调用函数的参数。举个例子:
12345678
// this function has `Function` in prototype chain// so `call` is availablefunctionmultiply(x,y){returnx*y;}multiply.call(null,3,5);// 15multiply(3,5);// same, 15
classExampleComponentextendsComponent{renderButton({title,name}){// without proper `this` it will failconst{isActive}=this.props;return(<Buttonkey={title}title={title}>{name}</Button>);}render(){const{buttons}=this.props;// without second param our function won't be able// to access `this` insideconstbuttonsMarkup=buttons.map(this.renderButton,this);}}
Math.max(1,2,3);// if we know all numbers upfront// we can call it like thatMath.max([1,2,3]);// won't work!Math.max.apply(null,[1,2,3]);// will work!// however, ES2015 array destructuring works as well:Math.max(...[1,2,3]);
// let's try to imagine how trim method is implemented// on String.prototypeString.prototype.trim=function(){// string itself is contained inside `this`!conststr=this;// this is a very naive implementationreturnstr.replace(/(^\s+)|(\s+$)/g,'');};// let's try to use `.call` method to invoke `trim`" aa ".trim.call(thisArg);// but `this` is our string itself!// so, next two calls are equivalent:" aa ".trim.call(" aa ");String.prototype.trim.call(" aa ");
Function.prototype.call=function(thisArg,...args){// `this` in our case is actually our function!constfn=this;// also, pretty naive implementationreturnfn.bind(thisArg)(...args);};
现在,我们可以来理一理所有的东西。当我们在 .map 里面声明函数的时候,我们给 Function.prototype.call 绑定String.prototype.trim 作为 this 上下文,然后我们在数组中的每个元素上调用这个函数,把每个字符串作为 thisArg 参数的值传递给 call。这意味着,String.prototype.trim 将使用字符串作为 this 上下文来调用。我们已经知道这样做是有效的,看看下面的例子: