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