我在php和javascript中有两个相同的代码块版本。它们的输出略有不同。Javascript输出中有两个"未定义"元素。我知道Javascript数组索引是增量的,从0开始,不允许我们跳过任何索引号。
是否有办法解决这个问题,使Javascript数组输出看起来像Php数组输出?
Php代码:$n = array();
$n[0] = 'Apple';
$n[3] = 'Apple';
echo "<pre>";
print_r( $n );
echo "</pre>";
输出:Array
(
[0] => Apple
[3] => Apple
)
Javascript代码:
var n = new Array();
n[0] = 'Apple';
n[3] = 'Apple';
n;
输出:[
"Apple",
undefined,
undefined,
"Apple"
]
谢谢! !
正如你提到的JavaScript数组有索引限制。
最接近的方式,你可以得到你正在寻找的输出是通过使用一个JavaScript对象。
如果您使用JavaScript JSON stringify将对象转换为格式良好的文本,您将得到几乎相同的输出。
您可以编写额外的JavaScript以使输出完全反映PHP输出。但我将把它留给你。
var n = new Object();
n[0] = 'Apple';
n[3] = 'Apple';
var output = JSON.stringify(n, null, 2);
// Output to a pre tag like the PHP example you gave.
document.getElementById("output").innerHTML = output;
// Simple output to the console.
console.log(output);
<pre id="output"></pre>
我认为在你的情况下更适合使用对象而不是数组,例如在JS关联数组相同的对象。例如
var n = {};
n[0] = 'Apple';
n[3] = 'Apple';
console.log(n);
它将输出
Object {0: "Apple", 3: "Apple"}
你可以从像array:
这样的对象中获取元素n[0], n[3]
PHP数组是哈希表,Javascript数组是索引列表
简短回答
。没有办法使Javascript数组在不违反ECMA标准的情况下表现得像Php数组(这意味着在技术上不再是Javascript)。
是的。但只能通过替换内置的Array原型行为。
参见ECMA-262 Section 15.4 Array Objects
数组到底是什么?
数组是有序数据
,仅此而已。虽然数组确实有index
,但数组"索引"的概念不应该与标记数据存储的概念混为一谈。数组索引总是顺序的,因为它指向数组中的位置,类似于人在一行中的位置。
你不可能让一个人排在前面,一个人排在第四,没有其他人在排队。n[0] = 'first'; n[3] = 'fourth;
几乎所有编程语言都是这样定义数组的,因为数据就是这样存储在内存中的。
用对象代替
对于这个问题,许多人已经给出了相同的答案。最终,javascript数组只是一个预定义的对象类型,按照上面概述的方式构建。因此,您试图改变的行为实际上是经过精心设计的行为。
所以,不要使用特殊的"Array"对象,而是使用字符串键(作为名为properties的对象),这样整个问题就简化了。
注意:这基本上是这里其他"使用对象"的答案所做的,有一个值得注意的例外。
n['0'] = 'Apple';
n['3'] = 'Apple';
// OR
n = {
'0': 'Apple',
'3': 'Apple',
};
// numeric keys are possible, IFF the var is first explicitly defined as an object.
n = {};
n[0] = 'Apple';
n[3] = 'Apple';
对象不够,它必须是一个数组?滚动你自己的"Array"容器对象
这里的缺点是你需要手动定义所有你想传递给数组对象本身的方法调用。
var PhpArray = function(ary){
if (ary instanceof Array) {
this.ary = ary;
} else {
this.ary = new Array(ary);
}
};
PhpArray.prototype.forEach = function(f){
for(i in this.ary){
if (this.ary[i] !== undefined && this.ary[i] !== null) {
f(i, this.ary[i]);
}
}
};
PhpArray.prototype.toString = function(){
var strResult '';
this.forEach(function(k, val){
switch(typeof val) {
case 'boolean':
case 'string':
case 'number':
strResult += k + ': ' + val;
break;
default:
if (val.toString) {
strResult += k + ': ' + val.toString();
} else {
strResult += k + ': ' + typeof val;
}
}
});
};
// Usage:
var n = Array();
n[0] = 'Apple';
n[3] = 'Apple';
var x = new PhpArray(n);
console.log('' + x);
x.ary[5] = 'Pear';
还是不够好?"改变数组的行为!?"
想从上面的例子访问x[3] = 'Apple';
吗?
或者你真的想重写内置的Array原型?
好吧,多萝西,系好你的安全带,因为javascript就要说拜拜了。没错,我们要去欧洲空气平衡指数之上的某个地方,在那里你可以做任何你想做的事。当然,其他开发人员会讨厌你,第三方工具(jQuery)也不再管用了,但至少你的javascript数组不再是数组了。 很遗憾,我不会帮你做那件事。你得到"undefined"值的原因是Javascript用"undefined"的值替换了数组键列表中任何缺失的索引/空白,即索引1和2在你的情况下。
不需要按键名将元素添加到数组中,只需将其推到数组的末尾:
n.push("Apple");
注意!这当然会导致Javascript中值的索引与PHP脚本不同,因为使用push总是会将值插入到数组的末尾。也就是说,要在两个脚本中以完全相同的方式进行插入,我建议您使用PHP的array_push方法,它的工作方式与Javascript的push方法相同。或者,您可以使用与PHP脚本相同的方法,但始终在数组末尾插入,例如:
$n[0] = 'Apple';
$n[1] = 'Apple';
值得注意的是,在js中迭代多维变量与php略有不同。
PHP$myArray = [0=>'here',1=>'we',2=>'go'];
for($i=0;$i<count($myArray);$i++){ echo $myArray[$i]; }
// or
foreach($myArray as $item){ echo $item; }
javaScript 有一些方法可以获得对象的长度,但它可能很棘手,所以:
myObject = {0:'here',1:'we',2:'go'};
for(item in myObject){ console.log(myObject[item]) }
在你的JS代码中:
n = n.filter(function(n){ return n != undefined });
console.log(n);
这将消除未定义的元素。和输出:
[
"Apple",
"Apple"
]
注意,如果在php中这样做:
echo $n[1] ;
你会得到:
注意:未定义偏移量:.....中的1
在Javascript数组中,它使用索引来查找值,所以如果它在该索引中没有找到任何值,它将其设置为未定义或空,以便删除未定义,我们可以使用此函数。
Array.prototype.remove = function(deleteValue) {
for (var i = 0; i < this.length; i++) {
if (this[i] == deleteValue) {
this.splice(i, 1);
i--;
}
}
return this;
};
var a = [];
a[0] = 'zero';
a[3] = 'three';
a.remove(undefined);
正如我所看到的,建议多个答案。如果您的需求只是为了显示数据,而不是为了生产发布。为了演示,你可以重写toString方法。下面是给定的代码片段。
// Override toString
Array.prototype.toString = function () {
return this.filter(x => x)
};
//How to use it
var n = new Array();
n[0] = 'Apple';
n[3] = 'Apple';
console.log(n.toString());
为什么要在console.log中使用toString。
控制台日志是否调用对象的toString方法