3

I am trying to subclass native window object, but when I do so none of the window methods are callable in child class.

Here is an example below:

<script type="application/javascript" >


function baseWindow () {


}
baseWindow.prototype = window;

var mywindow  = new baseWindow();

window.alert('works'); // works of course
alert(window.document); // accessing property of course works

mywindow.alert('doesn\'t work'); // alert doesn't work in subclass error: TypeError: Illegal invocation
mywindow.__proto__.alert('works') // accessing it directly via __proto__ works
alert(mywindow.document); // accessing document property works 

</script>

Can someone explain why that doesn't work and if there is workaround ?

Thanks

darkgaro
  • 567
  • 1
  • 6
  • 9

2 Answers2

3

As you figured out already, some properties of window are inherited properly, while others are not. Those that are not are methods that expect the object they are invoked on to be window which is obviously not the case in your example. By "expect" i mean they throw an error if the expectation is not met.

What you can do to avoid it is override those particular functions, perhaps by using the original functions somehow (depending on what you want to do with them).

function MyWindow(){
  this.alert = window.alert.bind(window); // override it to work!
}
MyWindow.prototype = window;

var mine = new MyWindow();
mine.alert(mine.location);

If you want many instances of Window and a single alert function shared between them and you don't want to alter window.alert, you need to add another object that inherits from window as prototype for Window:

function MyWindow() {
}
MyWindow.prototype = Object.create(window);

MyWindow.prototype.alert = window.alert.bind(window);

var mine = new MyWindow();
mine.alert(mine.location);
Tibos
  • 27,507
  • 4
  • 50
  • 64
  • Oh thanks your answer is also good, makes sense to do it that way – darkgaro Mar 17 '14 at 15:49
  • And I guess there is no way to bind or apply context to the whole window object without binding individually? I really only need to override one or two methods. – darkgaro Mar 17 '14 at 15:57
  • @darkgaro I found the other answer to be quite inaccurate, especially obvious being that he confused window with a constructor several times. npm's answer is much more accurate (with the proper way to inherit from regular functions and why it doesn't work for Window), though he excluded the possibility of inheriting from an object. – Tibos Mar 17 '14 at 15:58
  • @darkgaro There is no override all shortcut. You could go over each property in window in a for..in construct and redefine it on MyWindow.prototype, but i doubt you need that. If you only want to use one or two methods, just override them and you're done. – Tibos Mar 17 '14 at 16:01
  • Yeah thats what I thought but worth asking, thanks for your explanation. – darkgaro Mar 17 '14 at 16:05
0
I am trying to subclass native window object,

You cant.

Why? because window is not a function, and you cant call Window constructor.

Why? because the DOM is built that way.

function baseWindow () {


}
baseWindow.prototype = window

it's not even proper prototypal inheritance.

if Window constructor was callable one could write

function BaseWindow () {
  Window.call(this);
}
BaseWindow.prototype = Object.create(Window.prototype)

But you cant do that.

EDIT just to be clear,

window is an instance of Window, they are not the same.

mpm
  • 20,148
  • 7
  • 50
  • 55
  • I agree with the "you can't" part, but a prototype object in general doesn't have to be a function; it's an object. I mean, it's OK to write `baseWindow.prototype = { foo: function() { ... } };` – Pointy Mar 17 '14 at 14:47
  • You need to call the parent constructor somewhere to do prototypal inheritance. Or it's not prototypal inheritance – mpm Mar 17 '14 at 14:48
  • Why would you need to call a constructor on window ? – darkgaro Mar 17 '14 at 15:20