简体   繁体   中英

Explaining odd behavior in javascript

I saw this on twitter and I couldn't explain it either. Defining a onload function in the following two manner works:

1) JSFiddle

<html>
    <head>
        <script>
            onload = function(){
                alert('this works');
            };
        </script>
</head>
<body>
</body>
</html>​

2) JSFiddle

<html>
    <head>
        <script>
            window.onload = function(){
                alert('this works');
            };
        </script>
</head>
<body>
</body>
</html>​

But when defined like the following, it doesn't work even though it is assigned to window.onload

3) JSFiddle

<html>
    <head>
        <script>
            function onload(){
                alert('this doesnt work');
            };
            alert(window.onload); // this shows the definition of above function
        </script>
</head>
<body>
</body>
</html>​

What's going on here?

The first two examples assign a function to the window.onload property ( window. is implicit in the first example). The onload property actually belongs to the prototype of window (conveniently called Window ).

The third variant declares a new local function with the same name, and that function shadows the property from the prototype. This means, when you ask for window.onload , the engine finds the local version first, and gives up looking up the prototype chain. So alert(window.onload); does alert your function source. However, for the event handler to work, it would have to be assigned to the prototype object's onload property.

However, there is something odd going on: when you try to assign to a property that's inherited from the prototype , it shouldn't work, and an "own" property should be created on the object, shadowing the one from the prototype (eg http://jsfiddle.net/ssBt9/ ). But window behaves differently ( http://jsfiddle.net/asHP7/ ), and the behavior may even vary depending on the browser.

That's because onload is already declared and null before your script executes.

This is similar to that code :

var v=null;
function v(){
    console.log('hi');
}​​​​
console.log(v); // alerts null

which is different from this one :

function v(){
    console.log('hi');
}​​​​
console.log(v); // alerts the function

When you declare a function like this, the declaration and assignment are logically hoisted to the "start" of the scope, so the assignment doesn't really occur after the onload function is given the null value.

That's why it's different from

window.onload=...

which isn't a declaration but only an assignment which can't be hoisted.

In the first two cases your are defining a member of window called onload. In the third case your are only defining a function but is not a member of current window.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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