简体   繁体   English

在JavaScript中,不具有属性“ foo”的对象“ obj”如何使用obj [“ foo”]赋值?

[英]In JavaScript, how does an object “obj” that doesn't have the property named “foo” be able to give a value using obj[“foo”]?

I read in the book Secrets of the JavaScript Ninja, that we can use document.all["id"] to get all elements in the document that has such ID, if the browser supports it. 我在《 JavaScript忍者的秘密》一书中读到,如果浏览器支持的话,我们可以使用document.all["id"]获取具有此类ID的文档中的所有元素。 (although supposedly we should only have one element with a particular ID). (尽管据说我们应该只有一个具有特定ID的元素)。

But document.all returns an HTMLAllCollection object, and I see in Chrome that it has 9 elements, like an array (9 elements, as set up in jsfiddle). 但是document.all返回一个HTMLAllCollection对象,我在Chrome浏览器中看到它有9个元素,如数组(9个元素,在jsfiddle中设置)。 So I can understand why document.all[9] can return the element, but why can document.all["foo"] return it too? 这样我就能理解为什么document.all[9]可以返回元素,但是为什么document.all["foo"]也可以返回元素? If we define var obj = { foo : 123 } , then we can say obj["foo"] , but document.all is not an object with a key foo . 如果我们定义var obj = { foo : 123 } ,那么我们可以说obj["foo"] ,但是document.all不是带有键foo的对象。 So supposedly, document.all["foo"] shouldn't be able to return an element like that. 因此,据推测, document.all["foo"]不能返回这样的元素。

Note: this question is not to ask about the use of document.all , and it is not about asking to have two elements with the same ID on the page. 注意:此问题不是要询问document.all的使用,也不是要在页面上询问两个具有相同ID的元素。 It is asking why an object obj that does not seem to have the key foo is able to give a value using obj["foo"] I do not know why this is not a valid programming question. 这是在问为什么似乎没有键foo的对象obj能够使用obj["foo"]给出值,我不知道为什么这不是有效的编程问题。

sample code: 样例代码:

1 element with such ID: 1个具有以下ID的元素:
http://jsfiddle.net/ArR5x/5/ http://jsfiddle.net/ArR5x/5/

2 elements with such ID: 2个具有此类ID的元素:
http://jsfiddle.net/ArR5x/10/ http://jsfiddle.net/ArR5x/10/

Update: Dan Tao is correct. 更新:丹涛是正确的。 It is due to some properties being enumerable and some are not, and we can easily produce the same situation if ECMAScript 5 is supported: http://jsfiddle.net/Akdp9/12/ The is a valid question about JavaScript, and the real answer is that it is due to the enumerable attribute of a property. 这是由于某些属性是可枚举的,而有些则不是,如果支持ECMAScript 5,我们可以很容易地产生相同的情况: http : //jsfiddle.net/Akdp9/12/这是关于JavaScript的有效问题,而真正的答案是由于属性的可枚举属性。

I think I understand why you're confused. 我想我理解您为什么感到困惑。 Let me explain a couple of things to clear up any confusion. 让我解释一些事情以消除任何混乱。 Some of this you may already know, but I'm going to cover all of it just to be safe. 您可能已经知道其中一些内容,但是为了安全起见,我将介绍所有这些内容。

First, an array-like object can still have properties just like any other object. 首先,类似数组的对象仍然可以像其他任何对象一样具有属性。 Even a vanilla Array is like this. 甚至香草Array都是这样。

var arr = [1, 2, 3];
arr.foo = "bar";
arr["foo"]; // => "bar"

So it seems perfectly reasonable that after parsing the DOM, the browser populates document.all with properties corresponding to every ID on the page, even though HTMLAllCollection is rather array-like. 因此,在解析DOM之后,即使HTMLAllCollection非常类似于数组,浏览器在对document.all进行填充时,都具有与页面上每个ID对应的属性,这似乎是完全合理的。

Second, an object's properties are not necessarily all created equal. 其次,对象的属性不一定都相同。 You may have tried this and noticed a lack of any "foo" property: 您可能已经尝试过此操作,但发现缺少任何“ foo”属性:

Object.keys(document.all)
// => ["0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "length"]

However, "foo" really is a property of document.all . 但是,“ foo”确实 document.all的属性。 You can verify that pretty easily: 您可以很容易地验证这一点:

document.all.foo;
// => [<div id=​"foo">​hello​</div>​, <div id=​"foo">​world​</div>​]

document.all.hasOwnProperty("foo") // => true

The issue here is that it is not an enumerable property. 这里的问题在于它不是枚举属性。 This means it won't show up in a for / in loop, and it also explains why you don't see it when you all Object.keys . 这意味着它不会出现在for / in循环中,并且还解释了为什么当您使用所有Object.keys时都看不到它。

You can confirm this with the propertyIsEnumerable method : 您可以使用propertyIsEnumerable方法进行确认:

document.all.propertyIsEnumerable("foo"); // => false

So in the end it's not so much of a mystery. 因此,最后并不是一个谜。 Arbitrary properties can be assigned to the document.all object, just as they can with arrays. 可以将任意属性分配给document.all对象,就像使用数组一样。 And that is the case here; 就是这种情况。 the properties just aren't enumerable. 这些属性是无法枚举的。

DOM is not implemented in Javascript and most rules of Javascript don't apply to it. DOM不是用Javascript实现的,大多数Javascript规则都不适用于它。

For example, in Chrome !!document.all evaluates to false even though in Javascript rules, all objects are truthy. 例如,在Chrome !!document.all计算结果为false ,即使在Javascript中的规则,所有的对象都是truthy。

Just because you aren't supposed to have multiple elements with the same ID does not mean that you can't query them. 仅仅因为您不应该拥有多个具有相同ID的元素,并不意味着您无法查询它们。 A CSS selector will apply to multiple elements with the same ID, as will querySelectorAll : CSS选择器将应用于具有相同ID的多个元素,以及querySelectorAll

document.querySelectorAll('#foo');

can also return multiple elements. 也可以返回多个元素。

Here's the fiddle to prove it: http://jsfiddle.net/EgBbN/ 这是证明它的小提琴: http : //jsfiddle.net/EgBbN/

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM