I found something strange..
function Man(){
this.Man = "Peter";
}
after I call it. (not use it as a constructor)
Man()
I think a result will be
alert(Man.Man)//-->Peter
but.. I'm wrong , actually the result is :
alert(Man.Man)//-->undefined
alert(Man)//-->Peter
That was really confusing ,how it happened??
I'll explain you what is happening there.
1
function Man(){
this.Man = "Peter";
}
The this in Man() function is window.
2
Man();
You are calling the function. Which sets the global variable Man's value to "Peter".
Note that this.Man = "Peter" is equal to window.Man = "Peter" as this is referring to the window.
3
alert(Man.Man)
The function call Man(); in step 2 has made the Man from a function to a string variable. Now Man is a variable whose value is a string and it doesn't contain the property Man, so it is undefined.
4
alert(Man)
Now, you are actually alerting the global variable which was created in Man() call and it was set the value of "Peter"
I used the chrome console and had some other findings
function Man(){
this.Man = "Peter";
console.log("this", this);
}
Above this refers to Window. If you call the function Man() nothing is returned since the function does not return anything but sets the property Man on the window-object to be Peter. Your line Man.Man should return undefined in chrome. If you use Man().Man you will get undefined as well since this refers to the window object and the function Man() has no property Man. You could write
function Man(){
this.Man = "Peter";
return this.Man;
}
This returns the value Peter. If you want to have a property Man you could use a constructor function write
// set this.Man == window.Man to Peter
function Man() { this.Man = "Peter"; }
// create an constructor for each object Man
Man.prototype = { constructor: this.Man }
// create an object
var man = new Man();
// call his property which was set in the constructor of the prototype
man.Man;
Please ask for more help if anything is unclear.
Update as response to the comment
You can use a constructor without using prototype (see examples at mdn or this question if you use this syntax:
function Box(color) // Constructor
{
this.color = color;
}
var redBox = new Box("red");
var blueBox = new Box("blue");
redBox.color; // returns red
blueBox.color; // returns blue
To understand where this refers to you can take a look at understanding javascript this. In the box-example this refers to the new instance (object) of the "underlying class function". In function Man(){this.Man = "Peter"} the this refers to this.window. You can read more about protype in this book.
Related
I was learing prototypes in Javascript and got a lot about their usages. But I'm confused about the following that how it didn't work.
function Employee(name)
{
this.name = name;
}
Employee.prototype.code = "SIMPLE";
Employee.prototype.getName = function()
{
return this.name;
}
var a = new Employee("Manish");
var b = new Employee("Vikash");
a.__proto__.code // SIMPLE
a.__proto__.getName() // Undefined
Why we can't access a function on __proto__ while a.__proto__ == Employee.prototype returns true.
The context ( aka this ) is determined in javascript when you call a function. So here:
a.__proto__.getName()
the context is a.__proto __ , and that has not a name property, so it returns undefined. Here:
a.getName()
you call getName with the context being a, and a has a name...
You can access the function on the __proto__ object like you expect - but you're getting this behavior because you lose the binding to this when you call it this way so the function is not returning what you expect. The value of this is determed by the calling context. For the purpose of experimenting, you can try adding the binding back like this:
a.__proto__.getName.bind(a)()
// Manish
// or
a.__proto__.getName.call(b)
// Vikash
How does the new work differently in the 2 examples below? I see that the 2nd example is replacing the annoymous funciton with a variable, but in the second one, the function/class "Person" is actually being called. Does it make any difference if it's being called or not? I tried it without the calling and it still worked. So that led me to believe that new is actually calling the function and setting up this to be assigned to the instance variable.
var person = new function() {
this.setName = function(name) {
this.name = name;
}
this.sayHi = function() {
return "Hi, my name is " + this.name;
}
}
person.setName("Rafael");
console.log(person.sayHi()); // Hi, my name is Rafael
var Person = function() {
this.setName = function(name) {
this.name = name;
}
this.sayHi = function() {
return "Hi, my name is " + this.name;
}
}
var personTwo = new Person()
personTwo.setName("Rafael");
console.log(personTwo.sayHi()); // Hi, my name is Rafael
There would be almost no difference between these two examples, if it was a simple function like this:
(function() { console.log("IIFE"); })();
// or
var f = function() { console.log("Function"); };
f();
You just store your function in a variable, and then call it.
However, it makes a little difference, since it is related to JS OOP mechanisms. In the first case you get Object instance, and in the second you get Person instance. This makes difference in OOP sense.
var person = new function() { };
console.log("Is instance of: " + person.constructor.name);
console.log("There is no way to check instanceof in this case");
var Person = function() { };
var person = new Person();
console.log("Is instance of: " + person.constructor.name);
console.log(person instanceof Person);
In general, new and classes are supposed to be used as in the second case in order to enable the full functionality of JS OOP. There is absolutely no sense or/and advantage in using anonymous class constructor.
Whether or not it is assigned into a variable: does not matter. It is completely parallel to this example:
var x = 1;
console.log(x);
and
console.log(1);
Whether it needs to be called or not: A function with the new operator is always being called, but with new, parentheses are optional when no parameters are passed: new Person() is equivalent to new Person, but new Person("Joe") cannot be done differently.
In the second example, you are passing to the new operator the exact same function. You simply are using a reference (logically stored in a variable) instead of writing literal function just in place.
So, your second example is the same as:
var personTwo = new (function() {
[...]
})()
[...]
Which, in fact, is much the same as the first one:
var person = new (function() {
[...]
})
[...]
NOTE that the parentheses surrounding the function are absolutely optional in this case. You could be placed there seven if you like: (((((((function(){[...]}))))))).
The point here is that when you say «in the second one, the function/class "Person" is actually being called» you are WRONG there: That function, which acts as a constructor isn't being called by you. You are simply passing it as a parameter (the constructor function) of the new operator which is, in fact, who is actually calling the constructor with the rest of parameters you provided, if any.
See new syntax documentation:
new constructor[([arguments])]
The constructor is the function you pass to the new operator and the parameters are specified between parentheses. But they are fully optional (including the parentheses itself).
This is why new constructor; without parentheses works.
To be clear: What you thought happens (but not) would be written as:
var person = new ((function(){...})()) ();
...or, more verbosely:
var person = new (
(function(){ // Constructor builder.
[...]
return function(){...}; // Actual constructor.
})() // Constructor builder call
//v-- Parentheses to force builder to be called.
) (); // <-- Parameters (if any) passed to the constructor.
Let’s say I have a constructor function which I do not have access to. Into this constructor function I want to inject a self executing init method which gets executed whenever a new instance gets created from this constructor.
For example: let’s say there is a Cat constructor, but I unfortunatly do not have access to it:
function Cat() {
// ...code which I do not have access to
// ...maybe it comes from an external file or something?
}
And I can now of course do this to create new cats:
var coolCat = new Cat();
All is well and I have my new cat instance.
But now what I want is (if I actaully had access to the Cat constructor function body, which of course I do not!) something like this:
function Cat() {
this.roarOnInit = function() {
alert(’ROOOAAAR!’);
};
this.roarOnInit();
}
…so that when I do this:
var coolCat = new Cat();
…I actually get that cool ROAR-alert box!
I do understand how to add the method roarOnInit to the Cat constructor (Cat.prototype.roarOnInit = function …) but is there a way that I easily can add the call to the method (which gets executed whenever a Cat instance is created) to the constructor body?
This seems like such a trivial thing, and it’s probably super easy, but I just can’t seem to figure this out this afternoon! Thanks for bearing with me.
UPDATE
Thanks for the answers so far! I did forget one very important thing, and that is that I will not know in advance what the constructor function will be, or it's name etc. This is because I'm running this through a function which accepts any constructor as a parameter, and eventually returns the constructor (with it's original name/prototype) back.
Let's start with this definition of Cat:
function Cat(name){
this.name=name;
}
Cat.prototype.meow=function(){alert(this.name)}
Now, what we can do is to overwrite this with a new constructor that returns a regular Cat, but only after running our script:
var oldCat = Cat;
function Cat(name){
var self=new oldCat(name);
self.roarOnInit=function(){alert("ROOOOAAARRR")};
self.roarOnInit();
return self;
}
We can now do new Cat("Muffin"), and it will roar, and we'll still have access to properties on the original Cat prototype chain. I show this in an example snippet:
// just to be safe, define the original as oldCat()
function oldCat(name){
this.name=name;
}
oldCat.prototype.meow=function(){alert(this.name)}
//var oldCat = Cat;
function Cat(name){
var self=new oldCat(name);
self.roarOnInit=function(){alert("ROOOOAAARRR")};
self.roarOnInit();
return self;
}
var coolCat = new Cat("Muffin");
coolCat.meow();
Now, if you want to abstract this to accept any function, it's not too hard. We just have to do a bit of work with the constructor, to pass arguments. Javascript - Create instance with array of arguments
function injectToConstructor(C){
return function(){
var self = new (C.bind.apply(C,[C].concat([].slice.call(arguments))))();
console.log("object initiated:");
console.log(self);
return self;
};
}
Then we can do something like:
Cat = injectToConstructor(Cat);
var coolCat = new Cat("Muffin"); // logs 2 items
coolCat.meow();
This is because I'm running this through a function which accepts any constructor as a parameter, and eventually returns the constructor (with it's original name/prototype) back.
You cannot really. It's impossible to alter a function's behaviour, no way to "inject" code into it. The only way is to wrap the function, i.e. decorate it, and return a new one.
In your example, it would look like so:
function makeRoarer(constr) {
function Roar() { // new .name and .length, but that shouldn't matter
constr.apply(this, arguments);
this.roarOnInit();
}
Roar.prototype = constr.prototype;
Roar.prototype.constructor = Roar;
Roar.prototype.roarOnInit = function() {
alert(’ROOOAAAR!’);
};
return Roar;
}
class Cat { … } // whatever
var a = new Cat(); // nothing
Cat = makeRoarer(Cat);
var b = new Cat(); // ROOOAAAR!
I am learning javascript and would love help understanding the snippet of code.
From Object.DefineProperties definition, the first parameter is an object. Is MyObjectConstructor a declaration or an object. With a constructor function I would expect to call new to make it an object.
This is what is confusing me. Or as I read in Javascript functions are objects so do I treat it as an object and the this property is where all staticProps and instanceProps are added to?
var _prototypeProperties = function (child, staticProps, instanceProps) {
if (staticProps){
Object.defineProperties(child, staticProps)
};
if (instanceProps) {
Object.defineProperties(child.prototype, instanceProps);
}
};
function myFunction() {
function MyObjectConstructor(element) {
this.element = element;
this.initialized = false;
}
_prototypeProperties(MyObjectConstructor, {...}, {...});
}
Yes, (constructor) functions are objects as well in javascript, and you can add properties directly to them.
The _prototypeProperties function in your example snippet does put the staticProperties on the constructor, so that they could be accessed as MyObjectConstructor.myStaticProperty. It also does put instanceProps (better: "class properties", "prototype properties") on the MyObjectConstructor.prototype object, from where they are inherited by instances: (new MyObjectConstructor).myPrototypeProperty. Lastly, your MyObjectConstructor does put "real" (own) properties on the instances, specifically (new MyObjectConstructor).element and .initialised.
In JavaScript, once defined, the resulting functions act identically:
function Hat() { }
var Hat = function() { }
Conventionally the first is used to create objects (usually with new) and the second is used as a regular method.
The new operator, when preceding a function gets kinda weird. Using the new operator will:
create a new Object "it"
set the function being called as "it"s prototype
binds "it" to this within the function
overrides the return value of the function with "it". This overrides both explicit returns and implicit returns of undefined.
For example:
// first define Hat function
function Hat() { this.color = 'red' }
// calling with `new` implicitly returns a new object bound to the function
new Hat()
// > Hat { color: "red" }
// invoking without `new` implicitly returns `unefined`,
// but `this` points to Hat's parent object.
// If running in the browser, Hat's parent object would be `window`
// so now Window.color is set to "red"
Hat()
//> undefined
Window.color
//> "red"
Be careful with new, because the new object will be returned instead of any explicit returns.
var color = function() { return "blue" }
color()
//> "blue"
new color()
//> color {}
JavaScript is prototypal by nature. The new operator reflects neither prototypical nor classical inheritance. I avoid it when possible, although many popular libraries use it.
I recommend reading through Crockford's explanation of JavaScript's prototypal inheritance: http://javascript.crockford.com/prototypal.html
Its terse, but if you understand his 10 lines of demo code you'll be good.
Play with bind, call and apply, and different scoping contexts too. After understanding scoping and the prototypal nature, the rest is just syntax.
first : the function is the first type object in the javascript . it means you can deliver the function as value . for example :
function test(){
return function(){
console.log('function');
}
}
test()();
you return the function as return an object , function can be assigned and the function another kind of value !
var test = function(i) {
// body...
return i;
}
test('123');
a character string 'test' refer to a Anonymous function , you can understand that you transmit a function to a character string .
second : if you use new to create a instance via function , this function will be called construction function , normally it used to init the params , and the instance will take the construction function own property or method and prototype's property or method from the construction function .
third : the instance's property of "__proto__" is refer to the construction function's prototype object . this is why the instance can use the prototype's property or method from the construction function .
forth : if you create the instance by new , the this will refer to the instance object ! so that instance can use the property and method .
from your code :
var _prototypeProperties = function (child, staticProps, instanceProps) {
if (staticProps){
Object.defineProperties(child, staticProps)
};
// the properties from the own construction function , like this :
// this.element = element;
// this.initialized = false;
if (instanceProps) {
Object.defineProperties(child.prototype, instanceProps);
}
};
// the properties from the construction function's prototype object . like this :
// MyObjectConstructor.prototype.name = 'somebody';
// MyObjectConstructor.prototype.getName = function(){
// return this.name;
// }
I've done some leg work on getting this code to behave the way I want it to up to a certain point.
However I have encountered problem that requires a little bit of direction in helping me to solve the issue.
Problem to solve
Comments in code will explain what I am trying to archive..
var myArr = ["Brent white","brentw.white"];
function nameFoo (name){
var strSplit = name.split(" "); // splitting Brent White
var nameStr = this. myArr; // fetching Brent white string from myArr
console.log (strSplit,myArr[0]);
}
nameFoo("Brent White"); // calling nameFoo function
var myData = {
someData:"somedata",
someMoreData:"moredata",
myName:function(){
// I need to call nameFoo function through myName method.
// My hypothesis is that return will use the (this) keyword within the object?
}
};
// Here I need to call the method to have access my nameFoo? Correct me if I am wrong?
// Is this method invocation?
// Please help..Lost here...
To sum it up, I want myName method to call the nameFoo function. nameFoo will then give me myName method the result.
If someone could be kind enough to demonstrate how to get through this last step then I would be very grateful.
Pointing me in the right direction would also be greatly appreciated..
PS I am new to JS.
Be careful with the 'this' keyword. By calling nameFoo in a global context ie:
// some code
nameFoo(arg);
// some more code
'this' will always refer to 'window'. So, when you call myData.myName, even though this object calls the nameFoo method, 'window' will still be referenced in nameFoo's 'this'. 'this' is normally scoped to the object the function belongs to.
If you need 'this' to refer to one of your custom objects, use the Function prototype method "call" from within your myName function.
var myData = {
...
...
myName: function() {
nameFoo.call(this, someArgument);
};
Note that someArgument will be the argument passed to 'nameFoo' -- which will throw an error if you do not supply an argument. It's up to you to figure out what you want to pass.
More info about Function.prototype.call:
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/call
More info about Function.prototype.apply:
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/apply
The only real difference between the two is how you supply arguments to the function you are calling. With "call", you separate the arguments with commas (as you would when normally executing a function).
eg: nameFoo.apply(this, arg1, arg2, arg3);
With "apply", you supply the arguments as an array.
eg: nameFoo.apply(this, [arg1, arg2, arg3]);
I'm thinking this conceptually may help you out:
// Some names in array
var my_names = ["Brent White", "John Smith"];
// Returns name array [First, Last]
function nameParse(full_name) {
return full_name.split(" ");
}
// Person object (properties)
function Person(name) {
this.full_name = name;
this.name_array = nameParse(name);
this.first_name = this.name_array[0];
this.last_name = this.name_array[1];
}
// Create single person example
var brent = new Person(my_names[0]);
// Access properties of brent
console.log(brent);
console.log("Hey, my first name is " + brent.first_name);
// Alternate example --------- //
// Store our people here
var my_people = [];
// Create a person for each name
for (var i = 0, max = my_names.length; i < max; i += 1) {
var some_person = new Person(my_names[i]);
my_people.push(some_person);
}
console.log(my_people);