在这个MDN页面上[ 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;
}
});
}
Run Code Online (Sandbox Code Playgroud)
我的问题是这些行是什么:
var list = Object(this);
var length = list.length >>> 0;
Run Code Online (Sandbox Code Playgroud)
因为this肯定是一个数组(我们正在扩充Array.prototype)所以为什么要确保length是数字,为什么使用Object()?
T.J*_*der 11
根本的答案是,polyfill只是忠实地实现了ES6草案规范(截至5月22日草案的§22.1.3.8)中算法的第1步和第4步.
1.设O是调用ToObject传递此值作为参数的结果.
...
让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;
Run Code Online (Sandbox Code Playgroud)
......或通过Function#call或Function#apply.
所以假设我想Array#find在一个arguments对象上使用.arguments当然,它是类似数组但不是数组.所以我可能这样做:
function foo() {
var firstObject = Array.prototype.find.call(arguments, function(val) {
return typeof val === "object";
});
// ...
}
Run Code Online (Sandbox Code Playgroud)
一个更着名的例子(不涉及find)slice用于将类似数组的对象转换为数组:
function foo() {
// Turn the `arguments` pseudo-array into a real array
var args = Array.prototype.slice.call(arguments, 0);
}
Run Code Online (Sandbox Code Playgroud)