0

Suppose I want to have three objects of type Room. The three objects would be bedroom, livingroom and bathroom. Room has two properties length and breadth, and one method myFunc. I use constructor method to create the three required objects as:

function Room(len, bred, myFunc) {
        this.len = 5;
        this.bred = 8;  
        this.myFunc =  alert();
}

    var bedroom = new Room();
    var livingroom = new Room(); 
    var bathroom = new Room();

The problem is that when I run this script myFunc gets executed three times displaying the alert. What I thought was that since new keyword converts a function into an object it must not execute that object's method -- typeof new Room returns "object".

My question is:

  • if the statement new Room(); converts a copy of Room() function into an object then isn't this equvalent to object creation with literal notation? If yes then shouldn't var bedroom = new Room(); just assign properties of Room object to bedroom object? Why does it execute objects method?

  • How do I create objects without executing their methods?

user31782
  • 7,087
  • 14
  • 68
  • 143
  • I've soon noticed that even creating objects with literal notation executes it's method. – user31782 Apr 19 '16 at 04:54
  • 2
    You're not understanding the difference between `alert()` and `alert`. This has nothing to do with creating objects. – JLRishe Apr 19 '16 at 04:57
  • @JLRishe I thought a function must have brackets after it's name. What does javascript do when it see `alert`? Does it replace `alert` with it's definition? – user31782 Apr 19 '16 at 05:07
  • 1
    `alert` is a function, as is `function(x) { alert(x); }`. When you put parentheses after a function, the function gets executed: `alert("foo")` or `(function(x) { alert(x); })("foo")`. – Amadan Apr 19 '16 at 05:14
  • @Amadan _When you put parentheses after a function, the function gets executed_ Then why doesn't `alert(x);` get executed inside `function(x) { alert(x); }`? – user31782 Apr 19 '16 at 05:17
  • Because it is inside the function *definition*. It will get executed when the rest of the function gets executed. For example, `function setFoo() { foo = 3; alert("foo"); }` does not set `foo` to `3`, nor alert, until you call `setFoo()` later. Nothing inside the function *definition* gets done ever until that function is executed. But you can do `setFooByAnotherName = setFoo`, that would not execute `setFoo` - only `setFoo()` (or `setFooByAnotherName()`) would. – Amadan Apr 19 '16 at 05:21
  • @Amadan Thats' exactly what I thought before asking the question. Because I know `C` language and that's how function definitions works in `C`. But here everybody said `alert()` executes `alert` function inside `Room()`. Also `myFunc = alert` is of no use because I can't call `... myFunc("hello");`. – user31782 Apr 19 '16 at 05:24
  • 1
    It's not *quite* same as C, because JavaScript is object-oriented, and C isn't (and it's object-oriented in a "weird" way, different from C++, for example). The variable `this` is crucial; as is the fact that the difference between a function and a method is very flimsy. `alert` expects to be called like a method (`window.alert`; the fact that it can be called as `alert` is because there is no local variable `alert`, and `window` is the default receiver). You definitely should finish the chapter on objects in JS... – Amadan Apr 19 '16 at 06:56

3 Answers3

1

alert is the function and alert() executes it. It has nothing to do with how objects are created.

Keep in mind that alert needs to be wrapped because it is written in native code foreign to JavaScript.

So it should be (with clickable example):

function Room(len, bred, myFunc) {
  this.len = 5;
  this.bred = 8;
  this.myFunc = function(x) {
    alert(x)
  };
}

var bedroom = new Room();
var livingroom = new Room();
var bathroom = new Room();

bedroom.myFunc('This is the bedroom.');

Edit:

The main reason is that alert expects this to be bound to window. Meaning that the following will also work:

this.myFunc = alert.bind(window);

function Room(len, bred, myFunc) {
  this.len = 5;
  this.bred = 8;
  this.myFunc = alert.bind(window);
}

var bedroom = new Room();
var livingroom = new Room();
var bathroom = new Room();

bedroom.myFunc('This is the bedroom.');
timolawl
  • 5,434
  • 13
  • 29
  • But then how do I call `alert()` with `bedroom.myFunc`? It doesn't pop up the alert message. – user31782 Apr 19 '16 at 04:59
  • 1
    `bedroom.myFunc('this is the bedroom')` – timolawl Apr 19 '16 at 05:00
  • It gives the following error: _TypeError: 'alert' called on an object that does not implement interface Window._ – user31782 Apr 19 '16 at 05:02
  • Is this a backend project? You can only use [alert](https://developer.mozilla.org/en-US/docs/Web/API/Window/alert) if you're working with the browser. – timolawl Apr 19 '16 at 05:03
  • I am using mozila firefox console. I can use `alert()` in the consle but typing `bedroom.myFunc('this is the bedroom')` gives the error. – user31782 Apr 19 '16 at 05:05
  • 2
    Or you can try this 'this.myFunc = function(x){alert(x)};' – Abhishek Apr 19 '16 at 05:06
  • Yes what @Abikshek said. – timolawl Apr 19 '16 at 05:08
  • So now `alert(x)` doesn't execute it !!? I am more confused now. – user31782 Apr 19 '16 at 05:11
  • 1
    No, because it is inside a function definition. `function Room(...) {... alert("foo"); }` will not alert until you call `Room()` or `new Room()`; similarly, `this.myFunc = function(x) { alert(x) }` will not alert until you execute `this.myFunc("foo")`. – Amadan Apr 19 '16 at 05:12
  • But in my code alert() is also inside function `Room()'s` definition. – user31782 Apr 19 '16 at 05:15
  • ...and it's not executed until you do `var bedroom = new Room()`, thus executing the function that contains `alert()` call. – Amadan Apr 19 '16 at 05:16
  • @Amadan So does `var bedroom = new Room()` executes `Room()` and _then_ it converts Room's copy into an object which is assigned to `bedroom`? – user31782 Apr 19 '16 at 05:20
  • `new` operator does this (simplified): it will make a new object, then call the function as if it was a method on that object (i.e. with `this` being set to the new object). Thus, `var bedroom = new Room()` is roughly equal to `var bedroom = {}, saved_this = this; this = {}; Room(); this = saved_this;` (very, very, very oversimplified, as I don't want to confuse you with `.call` or `Object.create` or prototypes). – Amadan Apr 19 '16 at 05:26
  • Ok please post an answer and elaborate everything in that. What I get now is that `var bedroom = new Room()` does this: `bedroom.len = 5; bedroom.bred = 8;` and finally `bedroom.myFunc = alert();` -- which calls the function `alert`. – user31782 Apr 19 '16 at 05:31
  • @user31782 your code is executing the alert function when you do (); e.g. if you create a separate function `function hi(){console.log('hi');}` and assign your `this.myFunc = hi();` This will execute hi function and you will see 3 hi in console logs – Abhishek Apr 19 '16 at 05:36
  • As for why `this.myFunc = alert;` didn't work by itself without wrapping it, I believe it's because `alert` is a function written in native code foreign to JavaScript. – timolawl Apr 19 '16 at 05:41
  • @Abhishek Suppose I have an already written function `foo(){...}` and I want to assign it to an object's property then I'll always have to rewrite the whole definition inside the object's definition? – user31782 Apr 19 '16 at 05:45
  • 1
    No. you can assign `foo` to that object property. `obj.property = foo;` [Here's](https://jsfiddle.net/1a7djyhv/) a fiddler. – Abhishek Apr 19 '16 at 06:01
  • Ok, I just need to drop the brackets `()` in assignment operations. But not with `alert`. – user31782 Apr 19 '16 at 06:06
  • Also the case for `window.confirm` and `window.prompt`. – timolawl Apr 19 '16 at 06:22
  • This question and answer + comments consumed a lot of network bandwidth (http calls) and some amount of space in stackoverflow's content repository. @user31782 you should really accept this answer now :) – Abhishek Apr 19 '16 at 06:26
  • @Abhishek I still don't know what does `var bedroom = new Room();` exactly do. I need to finish MDN tutorial first. – user31782 Apr 19 '16 at 06:38
0

You are executing the function during assignment, that is why you see three executions with that code. Simply replace your assignment to the function name itself:

function Room(len, bred, myFunc) {
        this.len = 5;
        this.bred = 8;  
        this.myFunc =  alert;
}

    var bedroom = new Room();
    var livingroom = new Room(); 
    var bathroom = new Room();
buddy123
  • 5,679
  • 10
  • 47
  • 73
0

dont use brackets with alert. Brackets cause the alert to be executed. If you omit brackets, then a function alert will be assigned to your myFunc property.

or hor
  • 723
  • 3
  • 11