为什么JavaScript允许您将数组和函数存储在一个变量中?

时间:2023-02-08 15:41:48

I came across this by mistake one day while programming a game:

我有一天在编程游戏时遇到了这个错误:

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"

Why does JavaScript let you do this? Is this a glitch?

为什么JavaScript允许你这样做?这是一个小故障吗?

8 个解决方案

#1


37  

There are no arrays here. For example, Array.isArray(foo) is false.

这里没有数组。例如,Array.isArray(foo)为false。

Instead, you are giving foo four properties, named "0", "1", "2", and "3" [1], with different values. This is completely valid, because functions are objects; you can always attach properties, with whatever name you like, to objects.

相反,你给foo四个属性,名为“0”,“1”,“2”和“3”[1],具有不同的值。这是完全有效的,因为函数是对象;您始终可以使用您喜欢的任何名称将属性附加到对象。

You could also do:

你也可以这样做:

foo.otherProp = "hi!";

alert(foo.otherProp);

[1]: Note that property names are always converted to strings before setting them; doing foo[{ toString: function () { return "baz"; }] = 5 will be the same as foo["baz"] = 5 or foo.baz = 5. Similarly, doing foo[0] = "whatever" is the same as doing foo["0"] = "whatever".

[1]:请注意,属性名称在设置之前始终会转换为字符串;做foo [{toString:function(){return“baz”; }] = 5将与foo [“baz”] = 5或foo.baz = 5相同。同样,执行foo [0] =“whatever”与执行foo相同[“0”] =“无论什么” 。

#2


9  

Why does JavaScript let you store an array and a function in one variable?

为什么JavaScript允许您将数组和函数存储在一个变量中?

It doesn't. It lets you store a reference to a function in a variable. Functions are first-class objects in JavaScript, and so they can have properties, including ones with names like "0", "1", etc.

它没有。它允许您在变量中存储对函数的引用。函数是JavaScript中的第一类对象,因此它们可以具有属性,包括名称为“0”,“1”等的属性。

You're seeing a couple of things at play here:

你在这里看到了几件事:

  1. What I said above, functions are objects, and so you can add properties to them.

    我上面所说的,函数是对象,因此您可以为它们添加属性。

  2. You can add properties ad-hoc, there's no need to predefine them as in some other languages.

    您可以临时添加属性,不需要像在其他语言中那样预定义它们。

  3. In JavaScript, you can refer to a property using dot notation and a literal (foo.bar), or using bracketed notation and a string (foo["bar"]).

    在JavaScript中,您可以使用点表示法和文字(foo.bar)或使用括号表示法和字符串(foo [“bar”])来引用属性。

  4. When you use bracketed notation, the thing within the brackets is cast to a string if it isn't already one, so [0] is actually ["0"].

    当你使用括号表示法时,括号内的东西会被强制转换为字符串(如果它不是一个字符串),所以[0]实际上是[“0”]。

And yes, that last is true even when you're dealing with arrays, because standard arrays in JavaScript aren't really arrays. (There are recent additions, Int32Array and such, which are true arrays, but Array is not.)

是的,即使在处理数组时也是如此,因为JavaScript中的标准数组并不是真正的数组。 (最近有新增内容,Int32Array等,它们都是真正的数组,但Array不是。)

#3


4  

The answer is quite simple, and can be expressed as a syllogism (for my amusement).

答案很简单,可以表达为三段论(为了我的娱乐)。

All objects can have developer-defined properties1.
All functions are objects.
Therefore, all functions can have developer-defined properties.

所有对象都可以具有开发人员定义的属性1。所有功能都是对象。因此,所有函数都可以具有开发人员定义的属性。


1 Technically not all objects. "Hardened" objects cannot be mutated by untrusted code, and objects provided by the application embedding the JavaScript runtime can customize their behavior to prevent this. These are edge cases, though. Un-hardened objects created from within the JavaScript runtime should all exhibit this functionality, and most of the time these are the objects one is trying to mutate.

1技术上并非所有对象。 “硬化”对象不能被不受信任的代码变异,嵌入JavaScript运行时的应用程序提供的对象可以自定义其行为以防止这种情况发生。不过,这些都是边缘情况。从JavaScript运行时创建的未强化对象都应该具有此功能,并且大多数时候这些是试图变异的对象。

#4


3  

foo[0] in this case assigns the value to a property named "0". A function is an object and can have properties added to it.

在这种情况下,foo [0]将值赋给名为“0”的属性。函数是一个对象,可以添加属性。

In the same way, these two are equivilant:

同样,这两个是等价的:

foo["abc"]
foo.abc

#5


0  

Almost everything (including functions) in Javascript is an object, so you can give it extra properties like 0 and 1.

几乎Javascript中的所有内容(包括函数)都是一个对象,因此您可以为它提供额外的属性,如0和1。

#6


0  

First of all, your question has nothing to do with your title.

首先,你的问题与你的头衔无关。

The answer to the question asked in your title, "Why does JavaScript let you store an array and a function in one variable?", JavaScript is a dynamically typed language, and that means you can put whatever you like in a variable, and the interpreter won't complain.

在你的标题中提到的问题的答案,“为什么JavaScript允许你将数组和函数存储在一个变量中?”,JavaScript是一种动态类型语言,这意味着你可以把任何你喜欢的东西放在一个变量中,口译员不会抱怨。

In the body of your question, you wonder why you are allowed to set attributes of a function, as if it were an object or an array.

在你的问题正文中,你想知道为什么允许你设置一个函数的属性,就像它是一个对象或一个数组。

Well, you just can. That's the definition of the language. It's enormously useful to be able to add metainformation about a function.

嗯,你可以。这就是语言的定义。能够添加关于函数的元信息非常有用。

But yes, JavaScript is covered with sharp edges and pointy bits, so you have to be careful.

但是,是的,JavaScript有尖锐的边缘和尖头,所以你必须要小心。

#7


0  

In JavaScript, functions are first class objects.

在JavaScript中,函数是第一类对象。

function foo() {}
var isObject = foo instanceof Object;
// isObject is true

That's the deal with assigning functions to a variable, passing them as arguments, returning them from functions etc.

这是将函数赋值给变量,将它们作为参数传递,从函数等返回它们的处理。

Reference on MDN

MDN参考

#8


0  

What no one's mentioned so far is that this feature allows you to associate information with a function that might be useful to the function, but without polluting the global space with a lot of public data that might create collisions and so on.

到目前为止,没有人提到的是,此功能允许您将信息与可能对该功能有用的功能相关联,但不会使用可能产生冲突的大量公共数据来污染全局空间等等。

This is of course a feature of OOP/prototyping in general, but it has the added benefit of letting you call a function directly, and not as a property of a more general object.

这当然是OOP /原型设计的一个特性,但它有一个额外的好处,就是让你直接调用一个函数,而不是一个更通用的对象的属性。

#1


37  

There are no arrays here. For example, Array.isArray(foo) is false.

这里没有数组。例如,Array.isArray(foo)为false。

Instead, you are giving foo four properties, named "0", "1", "2", and "3" [1], with different values. This is completely valid, because functions are objects; you can always attach properties, with whatever name you like, to objects.

相反,你给foo四个属性,名为“0”,“1”,“2”和“3”[1],具有不同的值。这是完全有效的,因为函数是对象;您始终可以使用您喜欢的任何名称将属性附加到对象。

You could also do:

你也可以这样做:

foo.otherProp = "hi!";

alert(foo.otherProp);

[1]: Note that property names are always converted to strings before setting them; doing foo[{ toString: function () { return "baz"; }] = 5 will be the same as foo["baz"] = 5 or foo.baz = 5. Similarly, doing foo[0] = "whatever" is the same as doing foo["0"] = "whatever".

[1]:请注意,属性名称在设置之前始终会转换为字符串;做foo [{toString:function(){return“baz”; }] = 5将与foo [“baz”] = 5或foo.baz = 5相同。同样,执行foo [0] =“whatever”与执行foo相同[“0”] =“无论什么” 。

#2


9  

Why does JavaScript let you store an array and a function in one variable?

为什么JavaScript允许您将数组和函数存储在一个变量中?

It doesn't. It lets you store a reference to a function in a variable. Functions are first-class objects in JavaScript, and so they can have properties, including ones with names like "0", "1", etc.

它没有。它允许您在变量中存储对函数的引用。函数是JavaScript中的第一类对象,因此它们可以具有属性,包括名称为“0”,“1”等的属性。

You're seeing a couple of things at play here:

你在这里看到了几件事:

  1. What I said above, functions are objects, and so you can add properties to them.

    我上面所说的,函数是对象,因此您可以为它们添加属性。

  2. You can add properties ad-hoc, there's no need to predefine them as in some other languages.

    您可以临时添加属性,不需要像在其他语言中那样预定义它们。

  3. In JavaScript, you can refer to a property using dot notation and a literal (foo.bar), or using bracketed notation and a string (foo["bar"]).

    在JavaScript中,您可以使用点表示法和文字(foo.bar)或使用括号表示法和字符串(foo [“bar”])来引用属性。

  4. When you use bracketed notation, the thing within the brackets is cast to a string if it isn't already one, so [0] is actually ["0"].

    当你使用括号表示法时,括号内的东西会被强制转换为字符串(如果它不是一个字符串),所以[0]实际上是[“0”]。

And yes, that last is true even when you're dealing with arrays, because standard arrays in JavaScript aren't really arrays. (There are recent additions, Int32Array and such, which are true arrays, but Array is not.)

是的,即使在处理数组时也是如此,因为JavaScript中的标准数组并不是真正的数组。 (最近有新增内容,Int32Array等,它们都是真正的数组,但Array不是。)

#3


4  

The answer is quite simple, and can be expressed as a syllogism (for my amusement).

答案很简单,可以表达为三段论(为了我的娱乐)。

All objects can have developer-defined properties1.
All functions are objects.
Therefore, all functions can have developer-defined properties.

所有对象都可以具有开发人员定义的属性1。所有功能都是对象。因此,所有函数都可以具有开发人员定义的属性。


1 Technically not all objects. "Hardened" objects cannot be mutated by untrusted code, and objects provided by the application embedding the JavaScript runtime can customize their behavior to prevent this. These are edge cases, though. Un-hardened objects created from within the JavaScript runtime should all exhibit this functionality, and most of the time these are the objects one is trying to mutate.

1技术上并非所有对象。 “硬化”对象不能被不受信任的代码变异,嵌入JavaScript运行时的应用程序提供的对象可以自定义其行为以防止这种情况发生。不过,这些都是边缘情况。从JavaScript运行时创建的未强化对象都应该具有此功能,并且大多数时候这些是试图变异的对象。

#4


3  

foo[0] in this case assigns the value to a property named "0". A function is an object and can have properties added to it.

在这种情况下,foo [0]将值赋给名为“0”的属性。函数是一个对象,可以添加属性。

In the same way, these two are equivilant:

同样,这两个是等价的:

foo["abc"]
foo.abc

#5


0  

Almost everything (including functions) in Javascript is an object, so you can give it extra properties like 0 and 1.

几乎Javascript中的所有内容(包括函数)都是一个对象,因此您可以为它提供额外的属性,如0和1。

#6


0  

First of all, your question has nothing to do with your title.

首先,你的问题与你的头衔无关。

The answer to the question asked in your title, "Why does JavaScript let you store an array and a function in one variable?", JavaScript is a dynamically typed language, and that means you can put whatever you like in a variable, and the interpreter won't complain.

在你的标题中提到的问题的答案,“为什么JavaScript允许你将数组和函数存储在一个变量中?”,JavaScript是一种动态类型语言,这意味着你可以把任何你喜欢的东西放在一个变量中,口译员不会抱怨。

In the body of your question, you wonder why you are allowed to set attributes of a function, as if it were an object or an array.

在你的问题正文中,你想知道为什么允许你设置一个函数的属性,就像它是一个对象或一个数组。

Well, you just can. That's the definition of the language. It's enormously useful to be able to add metainformation about a function.

嗯,你可以。这就是语言的定义。能够添加关于函数的元信息非常有用。

But yes, JavaScript is covered with sharp edges and pointy bits, so you have to be careful.

但是,是的,JavaScript有尖锐的边缘和尖头,所以你必须要小心。

#7


0  

In JavaScript, functions are first class objects.

在JavaScript中,函数是第一类对象。

function foo() {}
var isObject = foo instanceof Object;
// isObject is true

That's the deal with assigning functions to a variable, passing them as arguments, returning them from functions etc.

这是将函数赋值给变量,将它们作为参数传递,从函数等返回它们的处理。

Reference on MDN

MDN参考

#8


0  

What no one's mentioned so far is that this feature allows you to associate information with a function that might be useful to the function, but without polluting the global space with a lot of public data that might create collisions and so on.

到目前为止,没有人提到的是,此功能允许您将信息与可能对该功能有用的功能相关联,但不会使用可能产生冲突的大量公共数据来污染全局空间等等。

This is of course a feature of OOP/prototyping in general, but it has the added benefit of letting you call a function directly, and not as a property of a more general object.

这当然是OOP /原型设计的一个特性,但它有一个额外的好处,就是让你直接调用一个函数,而不是一个更通用的对象的属性。