in this code below:
var a = 1;
var boat = { a:2,
innerBoat: {a:3,
print(){console.log(a);},
},
};
boat.innerBoat.print(); //output: 1
i don't understand why console.log(a); in print method returns the value 1.
Also, does the curly braces {} of the object referenced by boat creates a new private execution context in the stack at runtime ? (I know that only function calls create a new private execution context at runtime, but object creation confuses me, because they are originally a constructor call:
var boat = new Object();
i don't understand why console.log(a); in print method returns the value 1.
It logs the value of the variable a.
The properties of the various objects around it which also have the name a are not variables. They can only be referenced as properties of an object.
const a = 1;
const object = {
a: 2
};
console.log(a);
console.log(object.a)
See also How does the “this” keyword work? for how to access the property of an object that the method you are calling is attached to.
Also, does the curly braces {} of the object referenced by boat creates a new private execution context in the stack at runtime ?
No.
In javascript, an object really is nothing more than a collection of data, like a dictionary in many other languages.
var boat = new Object(); just creates an empty object, as if you did var boat = {};
If you're looking for something more like , you may try using ES6 classes
var a = 0
class Boat {
constructor() {
this.a = 1;
}
print() {
console.log(this.a);
}
}
var boat = new Boat()
boat.print(); //output: 2
Related
I have a variable at some point of a JavaScript code. Now I would like to get the name of the function (aka scope) where that variable was declared. So for example if that variable is a field of an oject, I would like to get the name of the object's type.
Consider the following code:
function MyClass() {
this.name = "MyName";
this.age = 20;
}
var myVariable = new window.MyClass();
alert(getDeclaringScope(myVariable)) // should alert 'window'
alert(getDeclaringScope(myVariable.name)) // should alert 'MyClass
Is there any way to implement the getDeclaringScope function?
UPDATE
I wanted to use some technic like this to access to access a kind of "static" variable where meta information is stored for knockoutjs observable. A farly simplified example:
var META = {};
META["MyClass"] = {};
META["MyClass"]["MyArray"] = { ElementType: "MyOtherClass" };
function MyClass() {
this.MyArray = ko.observableArray();
}
function MyOtherClass() {
this.name = "a";
}
ko.observableArray.fn.addFromPlainObjects = function(plainItems) {
var elemType = .... here I wanted to get "MyOtherClass" from the META global variable
// create MyOtherClass and map the plain items to it... etc.
}
No.
The object has a reference to its constructor, but the constructor could be referenced from many objects, not just window in this case. It could be accessed directly with a variable (as opposed to a property):
var MyClass = window.MyClass;
var foo = new MyClass();
You can create a back-reference explicitly in your object model, as constructor functions are objects.
window.MyClass.backref = window;
Though this is most likely not what you want. I suspect you have a misunderstanding regarding what the scope of a variable is; a variable scope has nothing to do with object properties. As such, there is no notion of "declaring scope" that represents the object and object property from which a variable reference was retrieved, as you seem to conceptualize it.
You can use instanceof and constructor:
Eg.
myVariable instanceof MyClass; //true
myVariable.constructor;
// returns
function MyClass() {
this.name = "MyName";
this.age = 20;
}
Check: instanceof and constructor
I have the following piece of code:
var Test = function () {
};
Test.prototype.doSomething = function() {
return "done";
};
Now, I create an object of Test
var t = new Test();
alert(t.doSomething()); // Correct alerts "done"
Now I add another method to the prototype:
Test.prototype.fly = function() { return "fly"; };
alert(t.fly()); // Correctly alerts "fly" (existing objects get "live udpated")
Now, I make the prototype point to a blank object:
Test.prototype = {};
alert(t.doSomething()); // Continues to alert "done", but why?
alert(t.fly()); // Continues to alert "fly", but why?
var t2 = new Test();
alert(t.doSomething()); // As expected, this does not work
When I add a method to prototype, it reflects correctly on all new and existing objects
When I "blank" out the prototype by doing <name>.prototype = {};, it only "blanks" out new instances, but not existing ones. Why?
An analogy is this:
var a = {foo : 'bar'};
var b = a; //the same object as a
var c = a;
var d = a;
a.apple = 'orange';
a = 1; //a === 1. b, c and d stay the same, pointing to the object with apple
What I did here is replace what a was pointing, but not the object itself.
When you added fly, you are modifying that single prototype object which all instances share, the object that Test.prototype is currently pointing to.
But when you assigned a blank object to Test.prototype, you modified what Test.prototype was pointing to. It does not modify what the existing instances are pointing to. But from this point on, any new instances will now use the new object on Test.prototype as their prototype object.
If you are familiar with C, I'd rather think of JS variables as pointers rather than references.
I'm completing the previous answer, if you want reflect your changes on all instances you must update the prototype correctly.
Prototype property is an object and you can delete a propery with the reserved keyword 'delete'.
If you want delete 'doSomething' property :
delete Test.prototype.doSomething;
consider
function Foo(){}
Foo.prototype = {a:{"VMAddress":"#1234"}}
consider that Foo.prototype.a object has VMAddress "#1234"
if you create object now then,
var f1 = new Foo();
now f1.a will point to the same object ie with Virtual Machine address "#1234"
if you look
f1.a === Foo.prototype.a ;//prints tue
If you change prototype to some other value now,
Foo.prototype = {a:{"VMAddress":"#5678"}}
and if you create object now then,
var f2 = new Foo();
although
f2.a === Foo.prototype.a; //prints true because both point to same VM address #5678
but
f1.a === f2.a; //prints false
why??
because their VM address are different(one is #1234 and other is #5678) and infact they are different object
final verdict
the prototype chain at the time of object creation decides what an object's prototype will be.
I'm learning javascript , so don't kill me.
I'm defining more different namespaces like this :
var name_Class = function(){
this.variable_name_1 = {}
this.method_name_1 = function() {}
}
and then..
var second_name_Class = function(){
this.variable_name_1 = {}
this.method_name_1 = function() {}
}
If i define and Initialiaze a variable in the first one and I try to call it in the second one , e.g. if a write c = new name_Class() it , e.g. redefine every array to [] so I cannot get the value I gave it before. Can you help me?
I'm not sure you understand what you're doing.
This
var name_Class = function(){
this.variable_name_1 = {}
this.method_name_1 = function() {}
}
defines a constructor function called name_Class (as an aside, constructors should have their first character capitalized by convention)
This
var c = new name_Class();
creates an object using that constructor. The new object is created and the constructor is bound to that object and called, setting the variable_name_1 and method_name_1 properties of the new object c. Each time you assign new name_Class() to a variable it will create a completely new object which has the constructor bound to it. Any changes you made to other objects created to the function will not have an effect on this new variable.
All of this is completely unrelated to your second Constructor, which you can use in the same way and is not affected at all by your first one.
Neither of these things are technically namespaces, they're classes or types. A namespace generally refers to a top level variable that other variables are defined as properties on. By default variables are defined on the global namespace, which for browsers is the window.
So to create your new object with type name_Class on a namespace namespace1 for instance, you could do
var namespace1 = {};
namespace1.c = new name_Class();
You can pass in arguments if you're looking to set values on an instance. eg
var Swatch = function(){
this.color = arguments[0] || 'green';
this.callback = arguments[1] || function() {
alert(this.color);
}
this.callback();
}
//defaults to green if no args are passed
var green = new Swatch();
//or pass in your own values
var red = new Swatch('red',function(){
alert('New swatch created with color '+this.color);
});
I am not quite sure how to state the question in word terms as I do not know what to call this -> Obj['var] = something.
I believe the title sums it up, is there any difference in declaring a variable or function of an object in those two different manners, or are they the same, different ways of doing the same thing.
EDIT:
An Example of my code:
Sorry for the confusing variable names, watch out for the capital characters :/
buttons = document.getElementsByClassName('button');
Buttons = new Button_Objs();
for (i = 0 ; i < buttons.length ; i++){
button = buttons[i];
Buttons['button' + i] = new Button(button);
}
var Button = function(elem){
this.buttonType = elem.getAttribute('button-type');
if (this.buttonType = 'safety'){
constructSafetyButton(elem, this);
}
}
function constructSafetyButton(elem, button){
button['setState'] = function(state){//do something}
}
I get yelled at by browsers when trying to use button.prototype.setState = func...
Obj['var'] = ... (and Obj.var = ... for that matter) assigns a property to the object which Obj is referring to.
Example:
var obj = {};
obj['foo'] = 'bar';
// or obj.foo = 'bar';
console.log(obj.foo); // shows 'bar'
Obj.prototype.var = ... will most likely throw an error, unless Obj is a function. Functions have a special property called prototype from which all new instances inherit when the function is called as constructor function, i.e. called with the new keyword.
Example:
function Foo() {}
Foo.prototype.bar = 'baz';
var foo = new Foo();
console.log(foo.bar); // shows 'baz'
Since functions themselves are objects too, you can assign properties to them as well
Foo.someProp = 'someVal';
but this does not influence instances created by Foo at all. New instances only inherit from Foo.prototype:
console.log(foo.someProp); // shows undefined
While both statements assign properties to objects (in this regard they are "the same"), the outcome is entirely different.
If you want to learn more about prototypal inheritance in JavaScript, have a look at MDN - Details of the Object Model and MDN - Inheritance and the prototype chain.
Based on the question in the title, no they are different.
Obj['var'] = something
is equivalent to this:
Obj.var = something;
Which is entirely different from setting a value on the prototype property of some object.
Obj.prototype.var = somthing
Whats the difference between (via prototypes)
var Todo = {};
Todo.prototype.name = "...";
Todo.prototype.hello = function() { ... }
Vs (variables & functions "outside" object)
var Todo = {}
Todo.name = "..."
Todo.hello = function() { ... }
Or even the below : variables & functions in object
var Todo = {
name: "...",
hello = function() { ... }
}
Think it like
A property or a function declared with prototype is an instance member of Todo.
A property or a function declared without prototype is a static member of Todo.
The first one doesn't make sense as you are dealing with an object instance (({}) instanceof Object === true), it won't have a prototype property (Object does).
You may be inquiring about the difference between these two patterns...
var ObjA = function() {
this.method = function() {};
};
var ObjB = function() {};
ObjB.prototype.method = function() {};
jsFiddle.
The former will use more memory when instantiated - each object has their own method. The latter won't each have their own method, the method lives on the prototype object, which is the next in command on the prototype chain when its attempted to be accessed on the parent.
Todo.prototype is also an object, so the difference is if you declare property with prototype, then every object who created from this prototype will have the property, otherwise, the property is only for Todo the object self.
A significant difference between method #1 and #2 (which is almost identical to example #3) is on new keyword that you need to use if you extend your function via prototype, e.g.
var Todo1 = function() {};
Todo1.prototype.name = "Foobar";
var Todo2 = {name: "Foobar" }
var a = Todo1;
console.log(a.name); // no property retrieved
var b = Todo2;
console.log(b.name); // Foobar
var c = new Todo1;
console.log(c.name); // Foobar