使用原型 apply vs this 来调用函数
Using prototype apply vs this to call function
在 MDN String 页面上,他们有一个 polyfill 示例 String.includes。
String.prototype.includes = function() {'use strict';
return String.prototype.indexOf.apply(this, arguments) !== -1;
};
他们使用 String.prototype.indexOf.apply
与直接在 this
上调用 indexOf
有什么原因吗?
String.prototype.includes = function(searchString, position) {'use strict';
return this.indexOf(searchString, position) !== -1;
};
是的,这样做是有原因的。它确保即使字符串的 indexOf
属性 被覆盖,仍然会使用原来的 indexOf
属性
如果我们使用 new String
构造函数,这样的事情是可能的。
var s = new String('test');
s.indexOf = function() {
throw new Error('this is bad');
};
s.indexOf('test');//Throws error.
String.prototype.indexOf
可以接受一个或两个参数,使用 apply 可以让你简单地传递进来的东西,因为它进来了,而不用担心类型或存在检查。
答案是使用 this.indexOf
的 polyfill 版本不符合 spec for String.prototype.includes
,它允许 this
是任何可转换为字符串的东西:
If searchString appears as a substring of the result of converting this object to a String...
例如,this
到 includes
可以是一个数字:
<< String.prototype.includes.call(1, '1')
>> true
这类似于 String.prototype.indexOf
,根据 spec 也不需要它的 this
是一个字符串。
<< String.prototype.indexOf.call(1, '1')
>> 0
如果 includes
按照 OP 建议的 this.indexOf
:
实施
String.prototype.includes = function(searchString, position) {'use strict';
return this.indexOf(searchString, position) !== -1;
};
然后使用非字符串 this
调用 includes
,如规范所允许,会生成 运行 时错误:
<< String.prototype.includes.call(1, '1')
>> TypeError: undefined is not a function
而 MDN polyfill:
String.prototype.includes = function() {'use strict';
return String.prototype.indexOf.apply(this, arguments) !== -1;
};
可以正常工作,利用 String.prototype.indexOf
的 this
也不必是字符串这一事实:
<< String.prototype.includes.call(1, '1')
>> true
所以我想 MDN polyfill 是这样写的,不是为了防止 indexOf
方法在某些特定字符串对象上被覆盖,或者作为 shorthand 以避免必须列出参数,或者由于某些克罗克福德人偏爱 prototype.apply
习语,而是为了正确实施规范。
在 MDN String 页面上,他们有一个 polyfill 示例 String.includes。
String.prototype.includes = function() {'use strict';
return String.prototype.indexOf.apply(this, arguments) !== -1;
};
他们使用 String.prototype.indexOf.apply
与直接在 this
上调用 indexOf
有什么原因吗?
String.prototype.includes = function(searchString, position) {'use strict';
return this.indexOf(searchString, position) !== -1;
};
是的,这样做是有原因的。它确保即使字符串的 indexOf
属性 被覆盖,仍然会使用原来的 indexOf
属性
如果我们使用 new String
构造函数,这样的事情是可能的。
var s = new String('test');
s.indexOf = function() {
throw new Error('this is bad');
};
s.indexOf('test');//Throws error.
String.prototype.indexOf
可以接受一个或两个参数,使用 apply 可以让你简单地传递进来的东西,因为它进来了,而不用担心类型或存在检查。
答案是使用 this.indexOf
的 polyfill 版本不符合 spec for String.prototype.includes
,它允许 this
是任何可转换为字符串的东西:
If searchString appears as a substring of the result of converting this object to a String...
例如,this
到 includes
可以是一个数字:
<< String.prototype.includes.call(1, '1')
>> true
这类似于 String.prototype.indexOf
,根据 spec 也不需要它的 this
是一个字符串。
<< String.prototype.indexOf.call(1, '1')
>> 0
如果 includes
按照 OP 建议的 this.indexOf
:
String.prototype.includes = function(searchString, position) {'use strict';
return this.indexOf(searchString, position) !== -1;
};
然后使用非字符串 this
调用 includes
,如规范所允许,会生成 运行 时错误:
<< String.prototype.includes.call(1, '1')
>> TypeError: undefined is not a function
而 MDN polyfill:
String.prototype.includes = function() {'use strict';
return String.prototype.indexOf.apply(this, arguments) !== -1;
};
可以正常工作,利用 String.prototype.indexOf
的 this
也不必是字符串这一事实:
<< String.prototype.includes.call(1, '1')
>> true
所以我想 MDN polyfill 是这样写的,不是为了防止 indexOf
方法在某些特定字符串对象上被覆盖,或者作为 shorthand 以避免必须列出参数,或者由于某些克罗克福德人偏爱 prototype.apply
习语,而是为了正确实施规范。