我有一天在编程游戏时错误地看到了这个:
var foo = function() { alert("Hello, World!"); }
foo[0] = "Zero";
foo[1] = "One";
foo[2] = "Two";
foo[3] = "Three";
foo(); // Alerts "Hello, World!"
alert(foo[2]); // Alerts "Two"
为什么JavaScript允许你这样做?这是一个小故障吗?
答案 0 :(得分:37)
这里没有数组。例如,Array.isArray(foo)
为false。
相反,您提供foo
四个名为"0"
,"1"
,"2"
和"3"
[1]的属性,具有不同的值。这是完全有效的,因为函数是对象;您可以随时将属性以及您喜欢的任何名称附加到对象。
你也可以这样做:
foo.otherProp = "hi!";
alert(foo.otherProp);
[1]:请注意,属性名称在设置之前始终会转换为字符串;执行foo[{ toString: function () { return "baz"; }] = 5
与foo["baz"] = 5
或foo.baz = 5
相同。同样,执行foo[0] = "whatever"
与执行foo["0"] = "whatever"
相同。
答案 1 :(得分:9)
为什么JavaScript允许您将数组和函数存储在一个变量中?
没有。它允许您在变量中存储对函数的引用。函数是JavaScript中的第一类对象,因此它们可以具有属性,包括名称为"0"
,"1"
等的属性。
你在这里看到了几件事:
上面所说的,函数是对象,因此您可以为它们添加属性。
您可以临时添加属性,无需像在其他语言中那样预定义它们。
在JavaScript中,您可以使用点表示法和文字(foo.bar)
,或使用括号表示法和字符串(foo["bar"]
)来引用属性。
当您使用括号内的表示法时,括号内的内容会被转换为字符串(如果它不是一个字符串),因此[0]
实际上是["0"]
。
是的,即使你正在处理数组,最后也是如此,因为标准arrays in JavaScript aren't really arrays。 (最近增加了Int32Array
等,这些都是真正的数组,但Array
不是。)
答案 2 :(得分:4)
答案很简单,可以表达为三段论(为了我的娱乐)。
所有对象都可以具有开发人员定义的属性 1 。
所有函数都是对象。
因此,所有函数都可以具有开发人员定义的属性。
1 技术上不是所有对象。 “硬化”对象不能被不受信任的代码变异,嵌入JavaScript运行时的应用程序提供的对象可以自定义其行为以防止这种情况发生。不过,这些都是边缘情况。从JavaScript运行时创建的未强化对象都应该具有此功能,并且大多数时候这些是试图变异的对象。
答案 3 :(得分:3)
foo[0]
将值分配给名为“0”的属性。函数是一个对象,可以添加属性。
以同样的方式,这两个是等价的:
foo["abc"]
foo.abc
答案 4 :(得分:0)
Javascript中的几乎所有内容(包括函数)都是一个对象,因此您可以为其提供额外的属性,如0
和1
。
答案 5 :(得分:0)
首先,你的问题与你的头衔无关。
您的标题中提到的问题的答案,“为什么JavaScript允许您将数组和函数存储在一个变量中?”,JavaScript是一种动态类型语言,这意味着您可以把你喜欢的任何东西放在一个变量中,翻译就不会抱怨。
在你的问题正文中,你想知道为什么允许你设置一个函数的属性,就好像它是一个对象或一个数组。
嗯,你可以。这就是语言的定义。能够添加关于函数的元信息非常有用。
但是,是的,JavaScript有尖锐的边缘和尖头,所以你必须要小心。
答案 6 :(得分:0)
在JavaScript中,函数是第一类对象。
function foo() {}
var isObject = foo instanceof Object;
// isObject is true
这是将函数赋值给变量,将它们作为参数传递,从函数等返回它们的处理。
答案 7 :(得分:0)
到目前为止,没有人提到的是,此功能允许您将信息与可能对该功能有用的功能相关联,但不会使用可能产生冲突等的大量公共数据来污染全局空间。 / p>
这当然是OOP /原型设计的一个特性,但它具有让你直接调用函数的附加好处,而不是更通用的对象的属性。