Javascript 有人能解释一下这个Array.prototype.find()polyfill吗?
在这个MDN页面上[ 这里有一个polyfill:Javascript 有人能解释一下这个Array.prototype.find()polyfill吗?,javascript,arrays,Javascript,Arrays,在这个MDN页面上[ 这里有一个polyfill: if (!Array.prototype.find) { Object.defineProperty(Array.prototype, 'find', { enumerable: false, configurable: true, writable: true, value: function(predicate) { if (this == null) { throw new
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;
}
});
}
既然
这个
肯定是一个数组(我们正在扩充array.prototype),那么为什么要确保长度
是数字的,为什么要使用Object()?基本答案是polyfill只是忠实地实现了ES6草案规范中算法的第1步和第4步(§22.1.3.8,从5月22日草案开始)
1.让O作为调用ToObject的结果,将this值作为参数传递
4.让len为ToLength(lenValue)
(其中ToLength基本上是一个数字的转换。)
由于现在可以为这个使用非对象值(通过函数#调用
和函数#应用
,或者通过在严格模式下直接调用函数),步骤1是有意义的
既然这个
肯定是一个数组(我们正在扩充数组.prototype
),那么为什么要确保长度是数字的,为什么要使用Object()
但是我们不知道这个是一个数组。请参阅当前ES6规范草案中的注释:
find
函数是有意泛型的;它不要求它的this
值是数组对象。因此,它可以传输到其他类型的对象以用作方法。能否将find
函数成功应用于非数组的外来对象取决于实现
您可以在几乎所有分配给原型的预定义函数中找到该注释
例如,您可以通过将它们直接分配给对象或其他原型,将它们用于其他用途:
MyNiftyThing.prototype.find = Array.prototype.find;
…或通过或
因此,假设我想在arguments
对象上使用数组#find
。arguments
当然类似于数组,但不是数组。因此我可以这样做:
function foo() {
var firstObject = Array.prototype.find.call(arguments, function(val) {
return typeof val === "object";
});
// ...
}
一个更著名的示例(不涉及find
)用于将类似数组的对象转换为数组:
function foo() {
// Turn the `arguments` pseudo-array into a real array
var args = Array.prototype.slice.call(arguments, 0);
}
此polyfill的问题在于它需要Object.defineProperty方法,这在未实现find的旧浏览器中不可用。如答案所示;此
不能保证是数组,您可以在以下答案中看到此
可以是什么(如果您需要比T.J.提供的更多信息):(在该变量的下)
function foo() {
// Turn the `arguments` pseudo-array into a real array
var args = Array.prototype.slice.call(arguments, 0);
}