This code throws an error.
try {
alert(hasOwnProperty('window'));
} catch(e) {
alert(e); // Type Error : can't convert undefined to object
}
but this code doesn't throws an error.
try {
alert(this.hasOwnProperty('window')); // true (if on browser)
} catch(e) {
// through catch block
alert(e);
}
Live Example | Live Source
As far as I kwon, func(arg)
is equal to this.func(arg)
if this
is Global Object. Why does such a thing happen?
I think what's going on is that we have an interaction of strict mode code and non-strict mode code. And in fact, when I dug up a copy of Firefox 3.6.15 (which doesn't support strict mode), I don't get the error using the link I posted to your question (it alerts "true" twice).
The code you've shown is, obviously, non-strict mode code. But what about the hasOwnProperty
implementation of the browser? I suspect it's strict, on browsers where strict mode is supported.
When you say
func();
...what the browser does is look up func
using standard identifier resolution, and then call it as though you did this:
func.call(undefined);
If func
is a loose-mode function, then within the call to func
, this
is the global object. But, if func
is a strict-mode function, this
within the call is undefined
.
In contrast, with this:
this.func();
...it again looks up func
(this time via property resolution using the prototype chain) and then effectively does this:
this.func.call(this);
In either strict or loose mode, that means this
within the function will be this
. (And of course, at global scope, this
is the global object.)
Here's an example of this interaction using code we can see rather than hasOwnProperty
:
(function() {
"use strict";
window.strictFunction = function() {
display("strictFunction: this === window? " +
(this === window));
display("strictFunction: typeof this: " +
typeof this);
};
})();
strictFunction();
strictFunction.call(undefined);
As you can see, that's loose code except for the bit defining a strictFunction
function on window
. Then we call that function twice from loose code. The result is this:
strictFunction: this === window? false strictFunction: typeof this: undefined strictFunction: this === window? false strictFunction: typeof this: undefined
In contrast, if we do that with a loose function, the result is:
looseFunction: this === window? true looseFunction: typeof this: object looseFunction: this === window? true looseFunction: typeof this: object
Complete example: Live Copy | Live Source
<!DOCTYPE html>
<html>
<head>
<meta charset=utf-8 />
<title>Fun With Strict Interactions</title>
<style>
body {
font-family: sans-serif;
}
p {
margin: 0;
}
</style>
</head>
<body>
<script>
(function() {
"use strict";
window.strictFunction = function() {
display("strictFunction: this === window? " +
(this === window));
display("strictFunction: typeof this: " +
typeof this);
};
})();
(function() {
window.looseFunction = function() {
display("looseFunction: this === window? " +
(this === window));
display("looseFunction: typeof this: " +
typeof this);
};
})();
display("Direct call:");
strictFunction();
looseFunction();
display("<hr>Call with <code>.call(undefined)</code>:");
strictFunction.call(undefined);
looseFunction.call(undefined);
display("<hr>Call with <code>.call(window)</code>:");
strictFunction.call(window);
looseFunction.call(window);
function display(msg) {
var p = document.createElement('p');
p.innerHTML = String(msg);
document.body.appendChild(p);
}
</script>
</body>
</html>
Output (using a JavaScript engine that supports strict mode):
Direct call: strictFunction: this === window? false strictFunction: typeof this: undefined looseFunction: this === window? true looseFunction: typeof this: object -- Call with .call(undefined): strictFunction: this === window? false strictFunction: typeof this: undefined looseFunction: this === window? true looseFunction: typeof this: object -- Call with .call(window): strictFunction: this === window? true strictFunction: typeof this: object looseFunction: this === window? true looseFunction: typeof this: object
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With