Javascript 数组键编号和";“数字”;意外地被认为是相同的
我一直在玩javascript数组,我遇到了一些不一致的地方,希望有人能给我解释一下 让我们从以下内容开始:Javascript 数组键编号和";“数字”;意外地被认为是相同的,javascript,arrays,type-conversion,Javascript,Arrays,Type Conversion,我一直在玩javascript数组,我遇到了一些不一致的地方,希望有人能给我解释一下 让我们从以下内容开始: var myArray = [1, 2, 3, 4, 5]; document.write("Length: " + myArray.length + "<br />"); for( var i in myArray){ document.write( "myArray[" + i + "] = " + myArray[i] + "<br />"); }
var myArray = [1, 2, 3, 4, 5];
document.write("Length: " + myArray.length + "<br />");
for( var i in myArray){
document.write( "myArray[" + i + "] = " + myArray[i] + "<br />");
}
document.write(myArray.join(", ") + "<br /><br />");
var myArray=[1,2,3,4,5];
文件。写入(“长度:“+myArray.Length+”
);
for(myArray中的变量i){
文件。写入(“myArray[“+i+”]=“+myArray[i]+”
”;
}
document.write(myArray.join(“,”+“
”);
长度:5
myArray[0]=1
myArray[1]=2
myArray[2]=3
myArray[3]=4
myArray[4]=5
1, 2, 3, 4, 5
这段代码没有什么特别之处,但我知道javascript数组是一个对象,因此属性可能会添加到数组中,这些属性添加到数组中的方式对我来说似乎不一致
在继续之前,让我注意一下如何在javascript中将字符串值转换为数字值
- 非空字符串->字符串或NaN的数值
- 空字符串->0
myArray[“某物”]=“某物”;
myArray[“”]=“空字符串”;
myArray[“4”]=“四”
for(myArray中的变量i){
文件。写入(“myArray[“+i+”]=“+myArray[i]+”
”;
}
document.write(myArray.join(“,”+“
”);
长度:5
myArray[0]=1
myArray[1]=2
myArray[2]=3
myArray[3]=4
myArray[4]=4
myArray[某物]=某物
myArray[]=空字符串
1,2,3,4,4
输出是意外的
设置属性myArray[“4”]时,非空字符串“4”被转换为其数值,这似乎是正确的。但是,空字符串“”未转换为其数值0,它被视为空字符串。此外,非空字符串“something”不会转换为其数值NaN,它被视为字符串。那是哪一个呢?myArray[]中的语句是数值上下文还是字符串上下文
另外,为什么myArray.length和myArray.join(“,”)中不包含myArray的两个非数字属性?JavaScript数组的键实际上是字符串。有关任意键的映射类型的详细信息和实现,请选中
澄清并补充Jason发布的内容:JavaScript数组是对象。对象具有属性。属性名称是字符串值。因此,数组索引也会在发生任何事情之前转换为字符串。如果满足以下条件(ECMA-262,15.4),则属性名P将被视为数组索引(即将调用特殊数组魔术): ToString(ToUint32(p))等于p,而ToUint32(p)不等于2^32− 一, 数字索引将转换为字符串(而不是相反的方式)很容易验证:
var array = [];
array[1] = 'foo';
array['1'] = 'bar';
array['+1'] = 'baz';
document.writeln(array[1]); // outputs bar
此外,在循环中使用“
for..in
循环”来迭代数组条目也是一种不好的做法——如果有人弄乱了一些原型,您可能会得到意想不到的结果(而且速度也不是很快)。将标准的用于(var i=0;i
。(编辑:以下内容不太正确)
JavaScript对象的键实际上是字符串。Javascript数组本身具有数字索引。如果您使用可以解释为非负整数的索引存储某些内容,它将尝试这样做。如果存储的索引不是非负整数(例如,它是字母数字、负数或带小数的浮点数),它将在数组索引存储中失败,并默认为对象(数组的基类)存储,然后将参数转换为字符串并按字符串索引存储--但是这些存储的属性不被数组类看到,因此对其方法/属性(长度、连接、切片、拼接、推送、弹出等)不可见
编辑:上面的说法不太正确(如Christopher的foo/bar/baz示例所示)。实际上,根据的实际存储索引是字符串,但如果它们是有效的数组索引(非负整数),那么数组对象的
[[Put]]]
方法是特殊的,它使这些特定值对数组的“array ish”方法可见。我不同意Christoph的说法“数组索引转换为字符串”
首先,我认为这取决于实现……我认为(好的)实现者会优化阵列访问,有一些聪明的方法可以做到这一点
事实上,我做了一个小测试,虽然它和大多数微基准测试一样好(即不是超级可靠),但它很有趣:
result = ""
var x;
var trueArray = []
var startTime = new Date();
for (var i = 0; i < 100000; i++)
{
x = "i" + i; // To do the same operations
trueArray[i] = 1;
}
var endTime = new Date();
result += "With array: " + (endTime - startTime) + "\n";
var sArray = []
var startTime = new Date();
for (var i = 0; i < 100000; i++)
{
x = "" + i;
sArray[x] = 1;
}
var endTime = new Date();
result += "With s array: " + (endTime - startTime) + "\n";
var objArray = {}
var startTime = new Date();
for (var i = 0; i < 100000; i++)
{
x = "i" + i;
objArray[x] = 1;
}
var endTime = new Date();
result += "With object(i): " + (endTime - startTime) + "\n";
var sobjArray = {}
var startTime = new Date();
for (var i = 0; i < 100000; i++)
{
x = "" + i;
sobjArray[x] = 1;
}
var endTime = new Date();
result += "With s object: " + (endTime - startTime) + "\n";
var iobjArray = {}
var startTime = new Date();
for (var i = 0; i < 100000; i++)
{
x = "" + i;
iobjArray[i] = 1;
}
var endTime = new Date();
result += "With i object: " + (endTime - startTime) + "\n";
// Then display result
result=“”
var x;
var trueArray=[]
var startTime=新日期();
对于(变量i=0;i<100000;i++)
{
x=“i”+i;//执行相同的操作
trueArray[i]=1;
}
var endTime=新日期();
结果+=”和数组:“+(结束时间-开始时间)+”\n”;
var sArray=[]
var startTime=新日期();
对于(变量i=0;i<100000;i++)
{
x=”“+i;
sArray[x]=1;
}
var endTime=新日期();
带s数组的结果+=“+(结束时间-开始时间)+”\n”;
var objArray={}
var startTime=新日期();
对于(变量i=0;i<100000;i++)
{
x=“i”+i;
objArray[x]=1;
}
var endTime=新日期();
结果+=“与对象(i):”+(结束时间-开始时间)+“\n”;
var sobjArray={}
var startTime=新日期();
对于(变量i=0;i<100000;i++)
{
x=”“+i;
sobjArray[x]=1;
}
var endTime=新日期();
结果+=“与s对象:”+(结束时间-开始时间)+“\n”;
var iobjArray={}
var startTime=新日期();
对于(变量i=0;i<100000;i++)
{
x=”“+i;
iobjArray[i]=1;
}
var endTime=新日期();
结果+=“带i对象:”+(endTime-startTime)+“\n”;
//然后显示结果
在IE6上,我得到:With array:1453 With object:3547在FF3.0上,我得到:With array:83 With object:226
在Safari 3.1上,我得到:With array:140 With object:313
在Opera9.26上,由于某种原因,我没有得到结果,但是如果我减少到循环数的十分之一,我会得到结果 Length: 5 myArray[0] = 1 myArray[1] = 2 myArray[2] = 3 myArray[3] = 4 myArray[4] = four myArray[someThing] = someThing myArray[] = Empty String 1, 2, 3, 4, four
var array = [];
array[1] = 'foo';
array['1'] = 'bar';
array['+1'] = 'baz';
document.writeln(array[1]); // outputs bar
result = ""
var x;
var trueArray = []
var startTime = new Date();
for (var i = 0; i < 100000; i++)
{
x = "i" + i; // To do the same operations
trueArray[i] = 1;
}
var endTime = new Date();
result += "With array: " + (endTime - startTime) + "\n";
var sArray = []
var startTime = new Date();
for (var i = 0; i < 100000; i++)
{
x = "" + i;
sArray[x] = 1;
}
var endTime = new Date();
result += "With s array: " + (endTime - startTime) + "\n";
var objArray = {}
var startTime = new Date();
for (var i = 0; i < 100000; i++)
{
x = "i" + i;
objArray[x] = 1;
}
var endTime = new Date();
result += "With object(i): " + (endTime - startTime) + "\n";
var sobjArray = {}
var startTime = new Date();
for (var i = 0; i < 100000; i++)
{
x = "" + i;
sobjArray[x] = 1;
}
var endTime = new Date();
result += "With s object: " + (endTime - startTime) + "\n";
var iobjArray = {}
var startTime = new Date();
for (var i = 0; i < 100000; i++)
{
x = "" + i;
iobjArray[i] = 1;
}
var endTime = new Date();
result += "With i object: " + (endTime - startTime) + "\n";
// Then display result
myArray["someThing"] = "someThing";
myArray.someThing = "someThing";
var start, end, count = 1000000;
var obj = {},
array = [];
start = new Date;
for(var i = count; i--; )
array[i] = i;
end = new Date;
document.writeln(Number(end) - Number(start));
start = new Date;
for(var i = count; i--; )
obj[i] = i;
end = new Date;
document.writeln(Number(end) - Number(start));