16

Lets say we have this code segment :

var name = ["Apples","Oranges","Strawberries"];
console.log(name.length);

This code produces this weird result of 27 !! The issue seems to be with using the variable name as 'name' which seems like a reserved keyword.

But can anyone explain why this weird behavior ?

ShadowFax
  • 391
  • 2
  • 11
  • I can't reproduce it: http://jsfiddle.net/barmar/w3QX2/ – Barmar Jan 06 '14 at 08:02
  • 3
    I can reproduce it on Chrome console : the array is cast to a string (hence the length). Obviously this changes the window.name property, and as it must be a string, it casts it. – Denys Séguret Jan 06 '14 at 08:02
  • Ahh, it depends on whether the code is inside a function. I reproduced it here: http://jsfiddle.net/barmar/w3QX2/1/ – Barmar Jan 06 '14 at 08:03

5 Answers5

13

It refers to window.name, which is the name of the window.

You can use the window's name to target hyperlinks, but it's not typically useful.

More info on window.name: https://developer.mozilla.org/en-US/docs/Web/API/Window.name

Just testing in chrome: You can't stop var name from being window.name, which is a string. No matter what you set the value to, it will be cast as a string so that it is a valid window name. So, name.length is the amount of characters in the string. It's best to avoid variable or be very careful about them!

As I can see from some of the other comments, this is an odd concept if you're new to it. The concern is over what window.name refers to. window.name is the name of the window. Any use of it is naming the window.

Defending that Chrome's behavior is logical:

If this var document = 'foo' did what it looks like it would do, you would have overwritten window.document - the document object - with a string. That would be quite the problem. name is a property of window just like document and has a use that shouldn't be (and can't be in Chrome) replaced.

m59
  • 43,214
  • 14
  • 119
  • 136
  • 1
    I believe any global variable can be referenced as `window.variable_name`, so in this case I guess it's predefined. – yitwail Jan 06 '14 at 08:08
  • @yitwail it's not a matter of that...`name` is special - it must be a string because of what it is used for. – m59 Jan 06 '14 at 08:10
  • 1
    @m59: The real issue is that global variables are "fields" of the window object. Even if it didn't get cast to a string, it would still be wrong - the name of the window would be overwritten by the array! – Luaan Jan 06 '14 at 08:11
  • @Luaan right, I'm trying to explain that in a way everyone would understand hehe. It's a bit abstract if you aren't used to it. – m59 Jan 06 '14 at 08:14
  • Yes, this indeed seems to be the problem because window.name shows up the same values when we set var name manually. And yes Firefox for instance doesn't seem to have this issue so it has to be a Chrome quirk. – ShadowFax Jan 06 '14 at 08:15
  • What FF does is too magical in my opinion. Chrome's behavior is consistent with the DOM+JS world. – Denys Séguret Jan 06 '14 at 08:16
  • 2
    @ShadowFax Chrome's behavior is the better one! Overwriting the window's name is comparable (but not as disastrous) as overwriting the document itself. – m59 Jan 06 '14 at 08:17
  • @dystroy: True, but it has its logic too. FF goes with the JS way of "variables can have their type changed", while Chrome goes with "window.name has a given type". – Luaan Jan 06 '14 at 09:03
  • @Luaan We're not really talking of variables but of accessors, here. – Denys Séguret Jan 06 '14 at 09:14
  • @dystroy: Which is basically a leaky abstraction manifesting - global variables are not really variables. As you say, when you (unknowingly) select a variable name, that is already in the window object, you get no warning, error or whatever - you just pretty much get undefined behaviour. This is as much a problem of DOM as it is of JS itself (ECMAScript defines a "global environment" in which global variables are stored, and in DHTML, the `window` object is this global environment, for better and worse). All I'm saying is that it would be helpful to get a warning when magic happens :) – Luaan Jan 06 '14 at 09:49
6

In the global scope, when you do var name = ["Apples","Oranges","Strawberries"];, it's the same as window.name = ["Apples","Oranges","Strawberries"];.

window.name must be a string, so it assign ["Apples","Oranges","Strawberries"].toString() to it which is "Apples,Oranges,Strawberries".

xdazz
  • 158,678
  • 38
  • 247
  • 274
2

What is the scope of variables in JavaScript? is a good start. Basically, when you're declaring name outside of a function, you're actually hiding the window.name value, which is a very, very bad idea (be very careful about any global variables you declare - they are actually values of the window object - including hiding existing values.

As others have said, the fact that Google Chrome forces the type to string is probably a Chrome quirk (although somewhat understandable), but the underlying cause is that you're simply doing something "dangerous" you didn't realize you're doing :)

Community
  • 1
  • 1
Luaan
  • 62,244
  • 7
  • 97
  • 116
0

As pointed out by others, in the when you are using the variable named name in the global scope it is treated as window.name.

From experimentation under Google Chrome, window.name gets the value as a string, like so: "Apples,Oranges,Strawberries", This behaviour is because Google Chrome is forcing window.name to be string. This explains why name.length will report 27 as that is the length of the string given.

This behaviour is not present in IE, Opera or Firefox which assing the array ["Apples","Oranges","Strawberries"] and report 3 on `name.length as expected, therefore I guess this is a quirk of Google Chrome.

Theraot
  • 31,890
  • 5
  • 57
  • 86
  • To me Chrome's behavior looks like the only logical behavior. – Denys Séguret Jan 06 '14 at 08:06
  • @dystroy True, but it only seems logical if you actually understand that global variables aren't variables at all, but rather, they assign to a "field" in the `window` object. This is a significant readability issue in (browser) JavaScript and it would be nice if the browser produced a warning ("you're declaring a variable that hides an existing field in `window`" or something like that). If you want to change `window.name`, just assign to `window.name`. Having `var name` do the same is very confusing. – Luaan Jan 06 '14 at 08:09
  • @dystroy I did refer to it as a quirk instead of bug because I think it makes sense. Although I have tested on Firefox, IE and Opera and they are not doing this. They assign the array and report `3` on `name.length` as expected. – Theraot Jan 06 '14 at 08:12
0

the window object has a property "name";

if you define 'name' in a closure function you may get 3

you defined var name in the global object, so you just initialized a string obj;

(function(){
  var name = ["Apples","Oranges","Strawberries"];
  consol.log(name.length);
})()

var name = ["Apples","Oranges","Strawberries"];

the global window.name is a build in string object(reserved), so name.toString() is called when you excuete the line above;

jingyinggong
  • 636
  • 5
  • 9