Reputation: 7912
I have a question regarding javaScript functions. Considering the following two function definitions:
// run time definition
var foo_1 = function () {
console.log("I ma foo 1");
}
// parse time definition
function foo_2 () {
console.log("I ma foo 2");
}
Since in javaScript every thing is an object, are two new objects created with name foo_1
and foo_2
in the previous code? If so, what is their prototype object and when are these objects created?
I am also struggling to understand the real difference between var obj={}
and var foo=function(){}
, both are objects, but the first has "type" Object
, while the second has type function
. Is this correct?
According to my book "JavaScript the good part", every new literal object is linked to Object.prototype
which by default is an empty object. In order to verify this behavior I tried to run the following script :
Object.prototype
//Object {}
Object.prototype = { name: "This is an experiment"};
//Object {name: "This is an experiment"}
function test() { conosle.log("Test"); }
test.prototype;
//Object {}
Why the result of test.prototype
is an empty object?
Finally, I was wondering if the these function definitions are equivalent to the following code:
this.foo = function() {
console.log("I ma foo");
}
If so, what's this
?
Upvotes: 4
Views: 179
Reputation: 25322
I think you have some confusion about functions and object's prototype, I hope I will be able to clarify a bit.
First of all:
function foo_2 () {
console.log("I ma foo 2");
}
This is called "function declaration", where:
var foo_1 = function () {
console.log("I ma foo 1");
}
Is called "function expression". You can have detailed information here: https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Functions_and_function_scope#Function_constructor_vs._function_declaration_vs._function_expression, with also the Function
constructor example.
Since in javaScript every thing is an object, are two new objects created with name foo_1 and foo_2 in the previous code?
Yes, they're objects, and if you modify the prototype
chains you will affect them:
Object.prototype.testName = "this is an experiment";
function test() {}
console.log(test.testName) // "this is an experiment"
But test.prototype
is an object too, so if you do:
console.log(test.prototype.testName) // "this is an experiment"
The reason because you do not get the property correctly it's probably because is inherited, and the console you're using (node, browser) displays only the own properties of an object (like Object.keys
), without crawl the whole prototype's chain.
That is the main reason because you shouldn't change the Object.prototype
: you will affect mostly everything and you can't predict the consequences.
I said "mostly" because you can create objects that actually doesn't inherit from Object
's prototype. You can do it using Object.create – or the non-standard where supported _proto_:
var foo = {};
console.log(foo.testName) // "this is an experiment"
var bar = Object.create(null);
console.log(bar.testName) // undefined
Finally, I was wondering if the these function definitions are equivalent to the following code:
this.foo = function() {
console.log("I ma foo");
}
It depends by what is this
when you execute this code. They're mostly equivalent if you execute the code in the global scope, so this
would be the global object (in browsers is window
). However, there is a difference. Using this syntax, you would be able to delete the foo
property, where you can't do that when is declared. So:
this.foo = function() {};
var bar = function() {};
delete foo // can be deleted;
delete bar // shouldn't be deleted;
See: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/delete
Upvotes: 1
Reputation: 39270
Yes var fn = function(){};
is of type Funcion
Why is test.porototype empty: Beacuse it's Function.prototype, not Object.prototype
What is this: answered in the link posted in the end
You can use a function as a constructor to create objects:
var Person = function(name){
this.name = name;
};
Person.prototype.walk=function(){
this.step().step().step();
};
In the example the Person is called a constructor function as it's an object you can give it properties as well like: Person.static="somthing"
this is good for static members related to Person like:
Person.HOMETOWN=22;
var ben = new Person("Ben");
ben.set(Person.HOMETOWN,"NY");
ben.get(Person.HOMETOWN);//generic get function what do you thing it'll get for ben?
ben.get(22);//maybe gets the same thing but difficult to guess
When you crate an instance using Person you have to use the new keyword:
var bob = new Person("Bob");console.log(bob.name);//=Bob
var ben = new Person("Ben");console.log(bob.name);//=Ben
The property/member name
is instance specific, it's different for bob and ben
The member walk can be used on all instances (bob and ben are instances of Person)
bob.walk();ben.walk();
Because walk() could not be found on bob (and later ben) JavaScript will look for it in the Person.prototype. There is only one walk function both bob and ben share this but the function will behave differently because in the walk function it uses this
.
If ben was waiting for a red light and you'll invoke walk and bob was at a green light then obviously something different would happen to ben and bob even though walk
does exactly the same for bob and ben but this
will refer to current object (bob for bob and ben for ben).
Shadowing members happens when I do something like ben.walk=22
, even though bob and ben share walk
the assignment of 22 to ben.walk will not effect bob.walk. This is because that statement will create a member called walk
on ben and assign it a value of 22. When asking for bob.walk you'll get the Person.prototype.walk function because walk
could not be found on bob. Asking for ben.walk however will get you the value 22 because the member walk has been created on ben and since JavaScript found walk on ben it will not look in the Person.prototype.
So when a member cannot be found on the instance the JavaScript engine will look on the constructor's prototype. So where does ben.hasOwnProperty come form? The instance ben doesn't have it, Person.prototype doesn't have it. The answer is that there is a prototype chain, Person's constructor is Function so when hasOwnProperty cannot be found on ben or or Person.prototype then it'll look on Person's constructor's prototype (is Funcition). If it cannot find hasOwnProperty there (but it can) then it'll look in Function's constructor's prototype (is Object).
Everything should inherit from Object.prototype unless you do Object.create(null,{})
which in my opinion is a bad idea. You can add things on Object.prototype (not a good idea either) and any object in JS will "inherit" that:
Object.prototype.yipee=function(){
console.log("yipeee");
};
22..yipee();//logs yipeee
"hello".yipee();//logs yipee
Now that you got the basics of it you can check out the following:
https://stackoverflow.com/a/16063711/1641941 (start with "the this variable" at the end)
Upvotes: 1
Reputation: 148524
Why the result of test.prototype is an empty object?
All functions have a prototype
property that initially references an empty object.
Definition : (resig)
Prototypes are used throughout JavaScript as a convenient means of defining properties and functionality that will be automatically applied to instances of objects.
You set the prototype
value of Object and not for the test
function.
in JS - every object - inherits Object.prototype
.
If you had attached a function to the Object.prototype
- as you wanted :
Object.prototype.name = function (){alert(1);};
function test() { console.log("Test"); }
var a = new test();
a.name();
It would alert 1
Regarding your comment :
What we really want to achieve is a prototype chain so that a Player can be a Person, and a Person can be a Mammal, and a Mammal can be an Animal, and so on, all the way to Object. The best technique for creating such a prototype chain is to use an instance of an object as the other object’s prototype:
SubClass.prototype = new SuperClass();
Consider this code :
function Person(){}
Person.prototype.dance = function(){};
function Player(){}
Player.prototype = new Person(); <------
var player = new Player();
assert(player instanceof Player,"player receives functionality from the Player prototype");
assert(player instanceof Person, "... and the Person prototype");
assert(player instanceof Object, "... and the Object prototype");
assert(typeof player.dance == "function", "... and can play!")
the noted line is what enable you make a player out of person ( and youll see that player is an instance of person!) :
http://jsbin.com/oNixIMo/8/edit
Upvotes: 4