Object literal and static variable - javascript

Object literal is considered as a static object.
So, object literal should contain only static variable, but in the following piece of code
var obj = {
a : "hello",
foo : function(){
console.log(this.a);
console.log(obj.a);
}
};
I can access a, in a static way obj.a and in a non-static way this.a.
Is a a static variable?

I think you are confusing a bunch of different things.
You've created an object named obj that has a field named a. That field can be accessed as obj.a (or obj['a'] if you prefer). If you arrange for some other variable to refer to obj, then it's also available via that variable.
One way to arrange for some other variable to point to obj is to take a field of obj which is defined as a function/closure, and invoke it using "method" syntax, as in obj.foo(). That means that inside the body of foo, for the duration of that invocation, the special variable this will refer to obj. Therefore code within that function can access obj.a via this.a.
None of this has anything to do with static vs dynamic scope, or singletons, or "class" vs "instance" members, or any of that. It's just an object.

The object literal is not a static class, it's an instance of Object; therefore obj.a can't be static either. Perhaps the confusion lies in the fact that the {} notation actually creates an object:
typeof {
a : "hello",
foo : function(){
console.log(this.a);
console.log(obj.a);
}
};
"object"
It's equivalent to:
var obj = new Object();
obj.a = 'hello';
obj.foo = function() {}
Conclusion
Static properties only have a meaning in class-oriented languages, but the same concept of classes in JavaScript is arguably non-existent.

obj.a is "static", the way you refer to it. You would only use this in this way when using new obj() - so obj would have to be a function.
By default this refers to the parent object when used inside a function that is an object member. In the case of your code obj is the parent object.
An example of using prototypes and this:
var Obj = function(){this.a = "hi"};
Obj.prototype.foo = function(){
console.log(this.a);
}
Obj.b = "sth";
var myObj = new Obj();
myObj.foo(); // "hi"
console.log(myObj.b); // undefined

This is not so simple , check the
let baba = {
a: 12,
foo: function () {
baba.a = 13;
this.a = 14;
},
roo: function () {
alert("baba.a = " + baba.a + "\nthis.a = " + this.a);
}
};
var theApp = {
start_action: function () {
let sola = Object.create(baba);
sola.foo();
sola.roo();
let bola = Object.create(baba);
bola.roo();
}
}
$(document).ready(theApp.start_action);
first call to foo after a roo() call we get : 13, 14
second call to foo 13, 13

Related

difference between Prototype constructor and private property

Consider the first scenario:
function f(){
console.log("inside the function : " + f.myVar);
}
f.prototype.myVar = 1;
var myObject = new f();
console.log("from the object : " + myObject.myVar);
And this is the output:
inside the function : undefined
from the object : 1
Question: why myVar isn't available in function? If it is stored in the objects prototype it is supposed to be accessible in f().
Now this scenario:
function f(){
console.log("inside the function : " + this.myVar);
}
f.prototype.myVar = 1;
var myObject = new f();
console.log("from the object : " + myObject.myVar);
And the output:
inside the function : 1
from the object : 1
Question: Why I'm getting different result? if 'this' refers to the object doesn't f.myVar mean access myVar in myObject ?
And now this scenario:
function f(){
console.log("inside the function : " + f.myVar);
console.log("inside the function using 'this' : " + this.myVar);
}
f.myVar = 1;
var myObject = new f();
console.log("from the object : " + myObject.myVar);
output:
inside the function : 1
inside the function using 'this' : undefined
from the object : undefined
So if I set a property without using prototype it should'nt be available in instantiated objects. But if I write the script like this, it'll deliver a strange result:
function f(){
console.log("inside the function : " + f.myVar);
}
f.myVar = 1;
var myObject = new f();
console.log("from the first object : " + myObject.myVar);
var strangeObject = myObject.constructor;
console.log("from the strange object : " + strangeObject.myVar);
Output:
inside the function : 1
from the first object : undefined
from the strange object : 1
Where does that "f.myVar" store? Whose variable is that? I'm confused what is the difference between all scenarios above. A complete carification would be much appreciated.
EDIT:
The main problem is that I don't know what this exactly mean:
function f(){}
f.someVar = someValue;
Because in other languages function is an abstract concept and in fact doesn't exist until it is called. Now in JS it is said that functions are objects by default. Ok so I should have an object like this by the script above:
{someVar : sameValue}
in fact I think this should be as same as:
function f(){this.someVar = someValue;} //should create {someVar : someValue}
If this is the case EVERY object instantiated by calling "new f()" must contain this "someVar" but they don't.
Start out by examining the definition of the word prototype. I think it's important to keep this in mind when thinking about how new objects are created in JavaScript.
pro·to·type
noun
a first, typical or preliminary model of something, especially a machine, from which other forms are developed or copied.
verb
make a prototype of (a product).
A prototype is a model from which another form will be copied.
When you create a new object in JavaScript, that is exactly what happens.
var obj = new MyObject();
In the above code, there are many things that happen, but in the context of the question, there are two things that happen which are relevant:
The prototype is applied to a new object.
The function MyObject is called, with this set to the new object.
With this knowledge in mind, let's take a look at the different forms of setting variables you have described:
function MyObject() {}
MyObject.myProperty = 'MyProperty';
It's important to understand that functions themselves are objects in JavaScript. Therefore, function MyObject is an object instance to itself. On the second line, we have set the property myProperty on this function object.
Refer back to the steps of creation above, and you will notice that it does not include applying properties from the function object to the new instance object. It only applies properties from the function object's prototype, and then runs the body of the function with this set to the new instance.
function MyObject() {
this.myProperty = 'MyProperty';
}
Here, the property myProperty is set on the individual instance.
function MyObject() {}
MyObject.prototype.myProperty = 'MyProperty';
In this example, each new instance of MyObject will be given its own property called myProperty and the value set to 'MyProperty'. From there, each instance can change its own myProperty to whatever value it needs without affecting the other.
function MyObject() {
console.log('myProperty', this.myProperty); //Will output 'Outside constructor.'
this.myProperty = 'Inside constructor.';
console.log('myProperty', this.myProperty); //Will output 'Inside constructor.
}
MyObject.prototype.myProperty = 'Outside constructor.';
The above example shows how myProperty is first applied from the prototype, then overwritten by the value applies in the function that is run.
Let's take a look at an example with all the forms you mentioned:
var output1 = document.getElementById('output1'),
output2 = document.getElementById('output2'),
output3 = document.getElementById('output3');
function MyObject(myProperty) {
this.myProperty = myProperty;
}
MyObject.myProperty = 'Function property.';
MyObject.prototype.myProperty = 'Prototype property.';
var obj = new MyObject('Constructor property');
output1.innerHTML = obj.myProperty;
output2.innerHTML = MyObject.myProperty;
output3.innerHTML = MyObject.prototype.myProperty;
<div id="output1"></div>
<div id="output2"></div>
<div id="output3"></div>
In the above example, you'll see how each can be referenced. Now examine it a little closer. Take a look at what happens with your 'Function property' when it is set from two different object instances:
var output1 = document.getElementById('output1'),
output2 = document.getElementById('output2');
function MyObject() {
//We are concatenating a string to the end of the property on each function call.
MyObject.myProperty += ' test ';
}
MyObject.myProperty = 'Function property.';
var obj1 = new MyObject();
var obj2 = new MyObject();
output1.innerHTML = MyObject.myProperty;
output2.innerHTML = MyObject.myProperty;
<div id="output1"></div>
<div id="output2"></div>
The above code demonstrates how the function level property is effectively shared. That's because it's not part of each instance. It's part of the function object.
Here I'll show you the process that takes place with the new operator, without actually using the new operator:
var output = document.getElementById('output');
//Let's have an object that has a prototype property with some properties:
var MyPrototypeObject = {
prototype: {
myPrototypeProperty: 'Prototype property'
}
};
//Let's specify a function that will be used as a constructor:
function MyConstructorFunction() {
this.myInstanceProperty = 'Instance property';
}
//First, new creates an object
var obj = {};
//Next, it applies all the properties from the prototype. We are using the MyPrototypeObject's prototype property for this example
for (var key in MyPrototypeObject.prototype) {
var val = MyPrototypeObject.prototype[key];
//Set the same property on the new object.
obj[key] = val;
}
//Now the prototype has been applied, let's apply the constructor function that was called.
MyConstructorFunction.call(obj); //This calls MyConstructorFunction with this set to obj.
output.innerHTML = 'myPrototypeProperty: ' + obj.myPrototypeProperty + '<br>' + 'myInstanceProperty: ' + obj.myInstanceProperty;
<div id="output"></div>
why myVar isn't available in function? If it is stored in the objects
prototype it is supposed to be accessible in f().
It's accessible in the function, but not as f.myVar, but as this.myVar or f.prototype.myVar.
Why I'm getting different result? if 'this' refers to the object
doesn't f.myVar mean access myVar in myObject ?
The function f is not the same as the object instance. The function is the constructor for the object, and using it with the new keyword creates an instance that is a separate object from the function.
When you use f.var, that is the property var of the function object. When you use this.var in the function, that is the property var in the object instance that the use of the new keyword created.
If you use f.var, that is a property of the constructor function object, so it will be the same variable even if you create multiple instances of the object, and it's only accessible using f.var.
If you use f.prototype.var, that will also be a variable that is the same for all instances of the object, but that can also be accessed using this.var as the object inherits the members of the prototype.
Example:
function f() {
console.log(f.var); // shows "42"
console.log(f.prototype.var); // shows "0.01"
console.log(this.var); shows "0.01";
}
f.var = 42;
f.prototype.var = 0.01;
If you want a variable that is local to each instance of the object, you should use neither of those. You should assign a value to this.var, which will make it a property in the object instance.
Example:
function f(value) {
this.var = value;
}
f.prototype.getValue = function(){
return this.var;
};
var instance1 = new f(42);
var instance2 = new f(0.01);
// now you have two instances with separate values:
console.log(instance1.getValue()); // shows "42"
console.log(instance2.getValue()); // shows "0.01"
As for question in edit, really all simple :-)
you have a function object function f(){}
you add to this object property, like you can add property to any other object in javascript f.someVar = 1
this not same as function f(){this.someVar = someValue;} because this in javascript depends on how function calling and can refers to created object, global object, or something else if called with call or apply function.
When you create object with new operator - you call f as constructor, and in this case this inside function referes to created object, and all properties added inside function as this.something = val add to created object.
Note: that you not use any property from function directly, so this not added to created object.
As for prototype: when you create object - you just set prototype property of created object to f.prototype object. So at end when you create object, you not use any property directly added to function object, just property from prototype and property that added manually to this in constructor
Seems you are getting confused with the prototype of function and object.
Here's a quote from the book Eloquent Javascript explaining the difference:
It is important to note the distinction between the way a prototype is
associated with a constructor (through its prototype property) and the
way objects have a prototype (which can be retrieved with
Object.getPrototypeOf). The actual prototype of a constructor is
Function.prototype since constructors are functions. Its prototype
property will be the prototype of instances created through it but is
not its own prototype.

Using 'this' to make values in object

var obj = {
name : 'object',
itis : this.name,
}
why is itis undefined? When I look at the values of the object itis value is blank. Thank-you.
The code
var obj = { name: 'object';
itis: this.name };
is perfectly equivalent to
var obj = {};
obj.name = 'object';
obj.itis = this.name;
in other words the this refer to the current this of the external scope and has nothing to do with the newly created object.
Things are different with
var obj = {};
obj.name = 'object';
obj.itisf = function(){ return this.name; }
console.log(obj.itisf()); // Shows "object"
and it happens because this, when executing the function, will become the object.
A simple rationalization is that when you call a function right after getting it from an object using . the this in that function will become the object. The rule implies also that in Javascript:
obj.f();
and
var ff = obj.f;
ff();
to not do the same thing, because in the first case only during the execution of the code in f the value of this will be the object. In the second case instead this will be the global object.
this is defined by the scope where it appears. So, you can't use this the way you want in an object literal, because the object literal doesn't have its own scope.
this has the meaning given to it by the current scope (i.e., the global scope or that of a function or method). You can do this:
var obj = {
name : 'object',
itis : 'object'
}
or this:
function Obj() {
this.name = 'object';
this.itis = this.name;
}
var obj = new Obj();
but what you're trying won't work. Here's an example of the problem in action:
function Foo() {
this.name = "My function";
var obj = {
name : 'My literal object',
itis : this.name
}
alert(obj.itis); // "My function"
}
Foo();
The alert shows My function because this is defined in the scope of Foo; obj doesn't have its own scope.
this keyword does not refer to the object even though you use that inside one. It just refers to the thing that initiated the current scope.
this refers to the object obj when you pass this in a function:
var obj = {
name : 'object',
itis : function(){
return this.name;
}
}
obj.itis();//'object'
'this' keyword refers to the current scope and in your case; you're using 'this' inside object literal declaration,and I guess, where 'this' would be referring to the 'Window' object.
if we see syntax wise, there would be no error. But at run time it will be 'Undefined'. Look at the below example
var xyz = {
a: 10,
b: 20,
c: this.a + this.b
};
document.write(xyz.a," and ",xyz.b);
document.write(xyz.c);
// to cross check
document.write(Window.a + Window.b);
// Why NaN ?
document.write( undefined + undefined );

is it possible to inherits object from object by using Literal notation way?

in short : is it possible to inherits object from object by using Literal notation way, or we must use Constructor way ?
For example: (Literal way)
var obj = {}, obj2 = {};
obj.str = "hello world!";
obj.printTxt = function () {
console.log(this.str);
};
obj2.prototype = obj.prototype; // occurs error message `(TypeError: obj2.printTxt is not a function)`
obj2.printTxt();
The root of the problem with your "literal notation" example is that obj.prototype does not exist. Objects do not have a meaningful property named prototype. The relationship between the object and its prototype is opaque and immutable - there is no standard way to determine what the prototype is, and there is no standard way to change it after it is constructed.
The closest you can get is the ES5 method Object.create.
var bar = {baz: []};
var foo = Object.create(bar);
is in every way equivalent to
var foo, bar = {baz: []};
(function () {
function Foo() {}
Foo.prototype = bar;
foo = new Foo;
})();
and creates an object foo whose prototype is (opaquely and immutably) bar.

How to access a variable inside a function in javascript?

I am extremely new to javascript so apologize for questions that may be trivial ?
var foo = function () {
a = "10";
this.b = "20";
};
foo.c = "30";
console.log(foo.a); // undefined
console.log(foo.c); // prints 30.
var foo1 = new foo();
console.log(foo1.b) // prints 20
How to access var "a" ? Is it even possible ?
Actually, as long as you don't prefix the variable declaration with var it will be global:
var foo = function () {
a = "10";
this.b = "20";
};
foo();
console.log(a); // is 10
Compared to:
var foo = function () {
var a = "10"; // private scope
this.b = "20";
};
foo();
console.log(a); // is undefined
Using global variables:
var a = 10;
var foo = function() {
a = 15;
this.b = 20;
};
console.log(a); // equals 10
foo();
console.log(a); // equals 15
If you wanted to actually access the variable a within the function, much like your example:
var foo = function() {
a = 10; // private member
};
There is no way to access that private member.
Turns out when you declare a variable in this way, you have created a global variable. You can access it with console.log(a); and it will return 10. However if you use var a = 10; inside the function, you will not be able to access this member.
What you can do is return an object in your constructor that defines public members:
function Foo() {
var a = '10';
function getA() {
return a;
}
return {
'a': a,
'b': 20,
'getA': getA
};
}
var foo = new Foo();
console.log(foo.a) // 10
console.log(foo.b); // 20
console.log(foo.getA()); // 10
The code
console.log(foo.a);
console.log(foo.c);
implies that you believe that a would be set as the equivalent of foo.a = "10", that is setting a static field of the "class" foo. This is not the case in JavaScript.
a = "10";
This sets the global variable a to the value "10", creating a global variable slot if necessary. This type of global assignment should be avoided and is caught by tools like JSLint.
this.b = "20";
This sets the field of the object passed as the this parameter of the function to "20", creating the field slot if necessary. Note that if you call foo directly, e.g. foo(), without new, the global scope is passed as this and this.b will also create a global variable. This type of error can be caught by strict mode. If you execute in strict mode, undefined is passed in as the this parameter and this will throw an exception.
var foo1 = new foo();
This creates a new, empty, object with the __proto__ property set to the value of the prototype property of foo and then calls foo passing the new object as the this parameter. All fields of __proto__ appear as the default values of fields of the object. This leads to the convention of adding methods to the prototype object of the constructor function and initializing fields in the constructor function. Inheritance can be simulated by constructing an object with the ancestor prototype object as its __proto__ value and assigning it to the functions prototype property of the constructor function. The constructor function would also call the ancestor constructor function (without new), passing its this as the constructor function's this parameter (using apply or call). This is all a bit awkward so ECMAScript 6 standardized this into a class construct which roughly translates to what I described.

Javascript find beginning of prototype chain

If I set a function to Object.prototype, and try to call the function from object Foo, is there a way for the function to know what object originally called it?
Object.prototype.MyFunc = function () {
console.log("I was called by " + (//object name here...));
}
Foo = {};
Foo.MyFunc();
Thanks!
AFAIK it's impossible because objects are objects, multiple variables can refer to the same object, no variable name is stored on the object unless done explicitly.
You can of course refer to the object at hand with this but you can't get the variable unless you did something like..
Object.prototype.alertName = function() {
alert( this.name )
}
var names = [
{name:'John'}
];
names[0].alertName()
As far as I know, it’s not possible to get the actual object name (i.e. var name).
You can however refer to the object the function was invoked upon by using this.
Object.prototype.MyFunc = function() {
this.foo = 'bar';
}
MyObject = {};
MyObject.MyFunc();
MyObject; // Object { foo = 'bar' }

Categories