Javascript 数组.of()是否按照es6中的指定工作?
根据文档,Javascript 数组.of()是否按照es6中的指定工作?,javascript,arrays,ecmascript-6,Javascript,Arrays,Ecmascript 6,根据文档,Array.of()是new Array()的一种替代方法,它允许您在运行时创建数组文字,即使它只有一个元素(new Array()出现故障的情况)。我喜欢这样,并且用.of()替换了对自定义数组子类的大多数new()调用,但是自从转换之后,我现在在尝试某些事情时发现了错误 该链接声称()的.of等同于: Array.of = function() { return Array.prototype.slice.call(arguments); } 为了检查这是否正确,我编写了这个测试
Array.of()
是new Array()
的一种替代方法,它允许您在运行时创建数组文字,即使它只有一个元素(new Array()出现故障的情况)。我喜欢这样,并且用.of()
替换了对自定义数组子类的大多数new()
调用,但是自从转换之后,我现在在尝试某些事情时发现了错误
该链接声称()的.of
等同于:
Array.of = function() { return Array.prototype.slice.call(arguments); }
为了检查这是否正确,我编写了这个测试来比较()的真实和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
构造函数应该能够手动处理文本(传入的参数),但由于上述原因,它无法访问它。有没有其他方法可以让我进入
这是对()的所建议的polyfill准确吗?还是我误解了JavaScript和构造函数的某些方面Array.of
允许您创建数组,而不是“数组文字”。“literal”指的是允许您描述和创建带有初始化数据(如果有)的数组的语法,如var a=[1,2,3]
最终,这些文件没有声称polyfill完全等效。MDN是一个wiki,因此如果polyfill可以改进,那么欢迎任何人贡献更改。请记住,它将在ES5及更低版本中工作,因此实现完整的子类化行为将需要更多的工作。因此,我们在这个问题中混合了多种内容。您正在使用不应该使用的扩展运算符,并且似乎对本机代码是什么存在误解。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”做得太多了。通过使用spread操作符,您已经获得了一个数组。这就足够了:
Array.of_polyfill = function (...args) {
return args;
};
在下面,您将获得相同阵列的三倍:
Array.of_polyfill=函数(…args){
返回args;
};
类扩展数组{
静态的(){
返回Array.prototype.slice.call(参数);
}
}
B类扩展了数组{
静态参数(…args){
返回args;
}
}
var a1=A.of(5,6,7,8);
var a2=一种聚填充物(5,6,7,8);
var b=b.of(5,6,7,8);
控制台日志(a1);
控制台日志(a2);
控制台日志(b)
假设调用构造函数时使用传递给A.of
的参数。那是错误的
让我们看一下以下各项的规格:
让len为传递给此函数的实际参数数
让items作为传递到此函数的参数列表
设C为该值的最大值
如果IsConstructor(C)
为真,则
a。让A是?构造(C,«len»)
否则,
a。让A是?ArrayCreate(len)
[……]
在我们的例子中,“C”是A
,您定义的类,它是一个构造函数。创建了A
的一个新实例,使用“len”(传递给Array.of
的参数数)调用构造函数
通常,构造函数是Array
,因此将调用Array(len)
。这里,调用A(4)
。因此,…args
是[4]
之后,算法将用正确的值填充新构造的数组
这意味着Array.of
和Array.prototype.slice.call
的结果是等效的,但不是它们内部的工作方式。经过一些测试后,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;
}
Array.of=function(){
//检查'this'是否为构造函数,否则返回'Array'构造函数
//在调用它之前,也许有更好的方法来确定“this”是否是构造函数。
var constructor=typeof this===“函数”和“原型”在此?this:Array中,
结果=新构造函数(arguments.length);
对于(var i=0;iYou正在扩展数组,但没有调用super()
为了正确初始化派生的对象,需要执行此操作。由于神奇的.length
属性不适用于ES5中的子分类,因此无法对数组的正确子类进行多填充。对于数组的真实子类,需要ES6,如果有ES6,则不需要数组。of()
polyfill@jfriend00:难道不能用setter和getter来模拟神奇的.length
吗?@spanky-不完全可以。你必须覆盖所有可能改变数组长度的操作来跟踪它。你可以创建一个包含数组的新对象,并将所有数组操作代理给它,然后使用.length
来自您所包含的实际数组,但它并不像您所展示的那样从数组继承。可以说,在ES5中尝试对数组进行子类化是不值得的。@jfriend00:Hmmm…我不认为内部操作实际使用了.length
属性