根据文档here,Array.of()
是new Array()
的替代方法,可让您在运行时创建数组文字,即使它只有一个元素(a新的Array()发生故障的情况。我喜欢这样,并用new()
替换了我的自定义数组子类上的大多数.of()
调用,但是由于转换我现在在尝试某些事情时发现错误。
该链接声称.of()
等同于此:
Array.of = function() { return Array.prototype.slice.call(arguments); }
为了检查这是否属实,我写了这个测试来比较真正的of()
和那个polyfill:
Array.of_polyfill = function( ...args ) // Fake of().
{
console.log( args );
return Array.prototype.slice.call( args );
}
class A extends Array // So we can peek inside what the real of() is doing.
{
constructor( ...args ) // Using of() on an "A" calls this constructor.
{
console.log( args );
return Array.prototype.slice.call( args );
}
}
var a1 = A.of ( 5,6,7,8 );
var a2 = A.of_polyfill( 5,6,7,8 );
a1和a2最终都包含正确的值[5,6,7,8]
,但在内部使用这两行是不一致的,如控制台日志中所示:
[4]
(4) [5, 6, 7, 8]
从第一行开始,调用.of()
并不会导致整个文字在范围内,而只是[4]
,就像在内部调用A
构造函数一样预分配四个槽,这不是polyfill所提到的。
我关心内部行为,因为of()
的一个主要建议用法是自定义数组子类,如上面的A
,以允许我指定新类型的数组文字。为此,我的A
构造函数应该能够使用文字(传入的参数)进行手动操作,但由于上述原因,它无法访问它。是否有其他方式可以访问?
建议of()
的polyfill是准确的还是我误解了JavaScript和构造函数的某些方面?
答案 0 :(得分:2)
次要点... Array.of
允许您创建一个数组,而不是“数组文字”。 “文字”是指允许您使用其初始化数据(如var a = [1, 2, 3]
)来描述和创建数组的语法。
最终,文档没有声明完全等效的polyfill。 MDN是一个wiki,所以如果可以改进polyfill,那么欢迎任何人提供更改。请记住,虽然它可以在ES5及更低版本中运行,但接近完整的子类化行为将会更加有效。
答案 1 :(得分:0)
所以我们在问题中混合了多个东西。您正在使用不应该使用的扩展运算符,并且似乎存在对本机代码的误解。 Array.of是一个静态函数;创建构造函数不会模仿其行为。但是,您可以覆盖静态方法并使用spread运算符。在这种情况下,它将是
class B extends Array {
static of(...args) {
return args;
}
}
或使用参数
class A extends Array {
static of() {
return Array.prototype.slice.call(arguments);
}
}
或者只是
class A extends Array {
static of() {
return Array.from(arguments);
}
}
同样,你的“polyfill”做得太多了。通过使用扩展运算符,您将获得一个数组。这就足够了:
Array.of_polyfill = function (...args) {
return args;
};
下面你会得到相同数组的三倍:
Array.of_polyfill = function (...args) {
return args;
};
class A extends Array {
static of() {
return Array.prototype.slice.call(arguments);
}
}
class B extends Array {
static of(...args) {
return args;
}
}
var a1 = A.of(5, 6, 7, 8);
var a2 = A.of_polyfill(5, 6, 7, 8);
var b = B.of(5,6,7,8);
console.log(a1);
console.log(a2);
console.log(b);
这是ecmascript6中的函数声明:
/**
@param {...null} items
@static
@return {Array}
*/
Array.of = function(items) {};
答案 2 :(得分:0)
您假设使用传递给select count(*), group_concat(id) as listIds
from posts p cross join
(select min(p.id) as minid
from posts p
where p.id > 3 and p.deleted = true
) pp
where p.id > 3 and (p.id < pp.minid or pp.minid is null);
的参数调用构造函数。那是错的。
让我们来看看Array.of
的规范:
- 让 len 成为传递给此函数的实际参数数。
- 让项成为传递给此函数的参数列表。
- 让 C 为此值。
如果
A.of
为真,那么一个。让 A 为
IsConstructor(C)
。- 醇>
否则,
一个。让 A 为
? Construct(C, « len »)
。[...]
在我们的例子中,“C”是? ArrayCreate(len)
,你定义的类,它是一个构造函数。创建了一个新的A
实例,使用“len”调用构造函数,这是我们传递给A
的参数数量。
通常,构造函数为Array.of
,因此将调用Array
。在这里,调用Array(len)
。因此,A(4)
为...args
。
之后,算法将使用正确的值填充新构造的数组。
这意味着[4]
和Array.of
的结果是等效的,但不是内部工作的方式。
答案 3 :(得分:0)
经过一些测试后,似乎Array.of()
的实际实现是这样的:
Array.of = function() {
//check wether `this` is a constructor, otherwise fall back to the `Array` constructor
//maybe there's a better way to determine wether `this` is a constructor _before_ calling it.
var constructor = typeof this === "function" && "prototype" in this? this: Array,
result = new constructor(arguments.length);
for(var i=0; i<arguments.length; ++i)
//FF and Chrome use defineProperty()
Object.defineProperty(result, i, {
value: arguments[i],
writable: true,
enumerable: true,
configurable: true
})
//Edge simply assigns the values
//result[i] = arguments[i];
//didn't test IE, Opera, Safari or any mobile browser
//and again, setting the length after the items have been defined
result.length = arguments.length;
return result;
}
为什么只是“某事” - 你没看过规范吗?
不,这是由浏览器中的实际行为驱动/推断的。而且只有“类似的东西”,因为我可能错过了一些东西。
特别是确定wet this
的部分是一个实际的构造函数,我并不完全满意。如果您使用箭头功能并手动添加名为prototype
的属性,它可能会产生错误匹配(然后抛出);但那种黑客行为应该非常罕见。
“经过一些测试” - 你测试了什么?
Function#call
调用它之间有区别,constructor
和constructor.prototype.constructor
不相同时的行为方式length
- proeprty(如果属性不是configurable:true
则抛出错误,但仅在FF和Chrome中)会发生什么情况