研究MDN Web文档上编写的find方法的polyfill,我没有遵循特定的行,让我共享代码
if (!Array.prototype.find) {
Object.defineProperty(Array.prototype, 'find', {
value: function(predicate) {
if (this == null) {
throw TypeError('"this" is null or not defined');
}
var o = Object(this);
var len = o.length >>> 0;
if (typeof predicate !== 'function') {
throw TypeError('predicate must be a function');
}
var thisArg = arguments[1];
var k = 0;
while (k < len) {
var kValue = o[k];
if (predicate.call(thisArg, kValue, k, o)) {
return kValue;
}
k++;
}
return undefined;
},
configurable: true,
writable: true
});
}
我的问题是表达式var o = Object(this);
。代替var o = this
这样做的目的是什么?在上述两种情况下打印值都会返回相同的对象。
这是调用var o = new Object(this);
的缩写吗?
我已从方法中删除了注释以缩短文本,这是polyfill实现的链接。
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/find#Polyfill
谢谢!
答案 0 :(得分:2)
在严格模式下,this
并不总是对象。 Object(this)
确保o
是对象,而不是基元。
下面是一个this
是原始语言的示例:
"use strict";
Object.defineProperty(String.prototype, "nishCap", {
writable: true,
configurable: true,
value() {
console.log(typeof this); // "string"
const o = Object(this);
console.log(typeof o); // "object"
return o.substring(0,1).toUpperCase() + o.substring(1);
}
});
const capped = "foo".nishCap();
请注意,这甚至适用于数组方法,因为您可以在非数组上调用它们,例如Array.prototype.find.call("foo", ch => ch === "o")
。
这是调用
var o = new Object(this);
的缩写吗?
否,new Object
总是创建一个新对象(并且不使用您提供的参数)。当您call Object
as a function时,它会将其参数强制转换为object。因此,原始字符串将成为String
对象,原始数字将成为Number
对象,等等。
代替
var o = this
这样做的目的是什么?
该polyfill紧跟the spec,其开头为:
- 让我们成为吗? ToObject(此值)。
在大多数情况下,这并不重要,但是如果在某些极端情况下将其遗弃会导致可观察到的行为与规格有所差异,我也不会感到惊讶。
答案 1 :(得分:1)
因为Array.prototype.find
可以使用{em>不是对象的this
值进行调用。参见specification:
调用find方法时,将执行以下步骤:
- 让我们成为吗? ToObject(此值)。
因此,为了完全符合规范,polyfill需要Object(this)
。否则,实现将有所不同,如以下两个代码片段所示:
'use strict';
const str = 'abc';
Array.prototype.find.call(
str,
(char, i, theThis) => {
// theThis should be an object, even if called on a non-object:
console.log(theThis);
}
);
'use strict';
Object.defineProperty(Array.prototype, 'find', {
value: function(predicate) {
if (this == null) {
throw TypeError('"this" is null or not defined');
}
// Without object wrapping:
var o = this; // <-------------------------------
var len = o.length >>> 0;
if (typeof predicate !== 'function') {
throw TypeError('predicate must be a function');
}
var thisArg = arguments[1];
var k = 0;
while (k < len) {
var kValue = o[k];
if (predicate.call(thisArg, kValue, k, o)) {
return kValue;
}
k++;
}
return undefined;
},
configurable: true,
writable: true
});
const str = 'abc';
Array.prototype.find.call(
str,
(char, i, theThis) => {
// The polyfill above had no object wrapping, so this result is not the same:
console.log(theThis);
}
);