javascript - 为什么我可以将命名属性添加到数组中,就像它是一个对象一样?
以下两个不同的代码片段似乎与我相同:
var myArray = Array();
myArray['A'] = "Athens";
myArray['B'] = "Berlin";
和
var myObject = {'A': 'Athens', 'B':'Berlin'};
因为它们的行为都相同,而且typeof(myArray) == typeof(myObjects)
(都产生'对象')。
这些变体之间有什么区别吗?
实际上,javascript中的所有内容都是一个对象,因此您可以通过在其上设置任意属性来“滥用”Array对象。 这应该被认为是有害的。 数组用于数字索引数据 - 对于非数字键,使用Object。
这是一个更具体的例子,为什么非数字键不适合“数组”:
var myArray = Array();
myArray['A'] = "Athens";
myArray['B'] = "Berlin";
alert(myArray.length);
这不会显示'2',而是'0' - 实际上,没有元素添加到数组中,只是添加了一些新属性到数组对象。
在JS数组中是对象,只是略微修改(带有更多函数)。
功能如下:
concat
every
filer
forEach
join
indexOf
lastIndexOf
map
pop
push
reverse
shift
slice
some
sort
splice
toSource
toString
unshift
valueOf
我认为,我以前的回答太隐喻和含糊不清。 澄清如下。
Array,Boolean,Date,Function,Number,RegExp,String的实例是一个Object,但使用特定于每种类型的方法和属性进行了增强。 例如,数组具有预定义的eval()
属性,而通用对象则没有。
javascript:alert([].length+'\n'+{}.length)
显示器
0 undefined
从本质上讲,FF Gecko解释器还区分了数组和通用对象,它们在评估语言结构方面存在明显差异。
javascript:
ra=[ "one", "two", "three"]; ra.a=4;
ob={0:"one", 1:"two", 2:"three"}; ob.a=4;
alert(
ra +"\n\n"+
ob +"\n\n"+
ra.toSource() +"\n\n"+
ra.a +"\t .toSource() forgot me! \n\n"+
ra.length +"\t and my length! \n\n"+
ob.toSource());
ps=""; for(i in ra)ps+=i+" "; alert(ps); /* NB .length is missing! */
ps=""; for(i in ob)ps+=i+" "; alert(ps);
显示
one,two,three [object Object] ["one", "two", "three"] 4 .toSource() forgot me! 3 and my length! ({0:"one", 1:"two", 2:"three", a:4})
和eval()
和function Object() { [native code] }
。
关于所有对象都是函数的声明:
使用任意对象实例作为像eval()
或function Object() { [native code] }
或true
或{}()
或obj()
这样的函数在语法和语义上都不正确,其中obj
是除Function
以外的任何类型,因此任意对象INSTANCE不是Function
.但是,给定一个对象 obj
和它的打字类型为Array, Boolean, Date, ...
,obj
怎么做Array, Boolean, Date, ...
? 什么是Array, Boolean, Date, ...
?
javascript:
alert([Array, Boolean, Date, Function,
Number, Object, RegExp, String] . join('\n\n') );
显示器
function Array() {
[native code]
}
function Boolean() {
[native code]
}
function Date() {
[native code]
}
function Function() {
[native code]
}
function Number() {
[native code]
}
function Object() {
[native code]
}
function RegExp() {
[native code]
}
function String() {
[native code]
}
在每种情况下,没有模棱两可,对象类型显示为eval()
定义,因此声明所有对象都是函数! (诙谐的是我故意模糊和模糊了对象实例与它的类型的区别!尽管如此,这表明“你不能拥有一个没有另一个”,对象和函数!大写强调类型为 与实例相反。)
功能和对象范例似乎都是编译和实现JS解释器低级内置基元的基础,例如eval()
和function Object() { [native code] }
和true
。
javascript:alert([Math, JSON, true.toSource()].join("\n\n"));
显示器
[object Math]
[object JSON]
(new Boolean(true))
在Javascript开发的时候,以对象为中心的编程风格(OOP的 - 面向对象的编程风格 - “我的自己的双关语!”)很流行,并且解释器同样用Java命名,以使其具有更高的可信度。 功能编程技术被降级为更抽象和深奥的考试,研究自动机,递归函数,形式语言等的理论,因此不适合。 然而,这些正式考虑的优势在Javascript中清楚地表现出来,特别是在FF的Gecko引擎中实现(即eval()
)。
函数的Object定义特别令人满意,因为它定义为递归关系! 使用它自己的定义定义!
eval()
并且由于函数是一个对象,因此相同的情绪成立function Object() { [native code] }
。
大多数其他定义停顿在静态终端值上。 但是,eval()
是一个特别强大的原语,因此String也可以嵌入任意功能。
请再次注意,上面使用的白话掩盖了对象类型和实例区别。
JavaScript中的所有内容都是除了原始类型之外的对象。
代码
var myArray = Array();
创建Array对象的实例
var myObject = {'A': 'Athens', 'B':'Berlin'};
创建Object对象的实例。
请尝试以下代码
alert(myArray.constructor)
alert(myObject.constructor)
所以你会看到区别在于对象构造函数的类型。
Array对象的实例将包含Array原型的所有属性和方法。
一个实际的区别是当在array
上使用JSON.stringify
时,将忽略所有非数字索引:
var arr = [];
var obj = {};
arr['name'] = 'John';
obj['name'] = 'John';
console.log(arr); // will output [name: "John"]
console.log(obj); // will output {name: "John"}
JSON.stringify(arr); // will return []
JSON.stringify(obj); // will return {"name":"John"}
JavaScript中数组和其他对象之间的区别。 虽然数组具有神奇的更新长度属性,但对于除数组之外的对象,无法实现此类属性。
var arrName = [];
arrName[5] = "test";
arrName.length; // <- 6
数组用于存储带有序数索引的东西 - 像传统的数组,堆栈或队列一样使用它。 对象是哈希 - 将其用于具有不同密钥的数据。
{}
-notation只是语法糖,使代码更好;-)
JavaScript有许多类似的结构,比如函数的构造,其中function()只是它的同义词
var Func = new Function("<params>", "<code>");