[https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/find] 有这个polyfill:
if (!Array.prototype.find) {
Object.defineProperty(Array.prototype, 'find', {
enumerable: false,
configurable: true,
writable: true,
value: function(predicate) {
if (this == null) {
throw new TypeError('Array.prototype.find called on null or undefined');
}
if (typeof predicate !== 'function') {
throw new TypeError('predicate must be a function');
}
var list = Object(this);
var length = list.length >>> 0;
var thisArg = arguments[1];
var value;
for (var i = 0; i < length; i++) {
if (i in list) {
value = list[i];
if (predicate.call(thisArg, value, i, list)) {
return value;
}
}
}
return undefined;
}
});
}
我的问题是以下几行:
var list = Object(this);
var length = list.length >>> 0;
因为this
绝对是一个数组(我们正在扩充Array.prototype)所以为什么要确保length
是数字,为什么使用Object()?
答案 0 :(得分:11)
根本的答案是,polyfill只是忠实地实现了ES6草案规范中的算法的第1步和第4步(截至5月22日草案的第22.1.3.8节)。
1。设 O 是调用ToObject传递 this 值作为参数的结果。
...
4。让 len 为ToLength( lenValue )。
(ToLength基本上是转换为数字。)
因为现在可以使用this
的非对象值(通过Function#call
和Function#apply
,或者只是在严格模式下直接调用该函数),步骤1才有意义
因为
this
绝对是一个数组(我们正在扩充Array.prototype
)所以为什么要确保长度是数字,为什么使用Object()
?
但我们不知道this
是一个数组。请参阅当前ES6草案规范中的这一说明:
find
函数是故意通用的;它不要求其this
值为Array对象。因此,它可以转移到其他类型的对象以用作方法。find
函数是否可以成功应用于非Array的异常对象是依赖于实现的。
您将在几乎所有分配给原型的预定义函数中找到该注释。
例如,您可以将它们用于其他事情,或者直接将它们分配给对象或其他原型:
MyNiftyThing.prototype.find = Array.prototype.find;
...或通过Function#call
或Function#apply
。
所以假设我想在Array#find
对象上使用arguments
。当然,arguments
是 array-like ,但不是数组。所以我可能会这样做:
function foo() {
var firstObject = Array.prototype.find.call(arguments, function(val) {
return typeof val === "object";
});
// ...
}
一个更着名的例子(不涉及find
)正在使用slice
将类似数组的对象转换为数组:
function foo() {
// Turn the `arguments` pseudo-array into a real array
var args = Array.prototype.slice.call(arguments, 0);
}