I want to create a new object from a nested object, something like this:
function MyObject(){
this.myProp;
this.myMethod = function(){};
this.MyNestedObject = new function(){
this.myNestedProp;
this.myNestedMethod = function(){};
}
}
obj = new MyObject();
myNestedObj1 = new obj.MyNestedObject;
myNestedObj2 = new obj.MyNestedObject;
myNestedObj3 = new obj.MyNestedObject;
I've tried several variations on this with no luck. Is there a proper syntax to accomplish this?
The error is in the new keyword, in the line:
this.MyNestedObject = new function(){
Whenever you use the new keyword, you are actually instantiating a new object, and then it turns out not to be a function anymore.
Try this:
function MyObject(){
this.myProp;
this.myMethod = function(){};
this.MyNestedObject = function(){
this.myNestedProp;
this.myNestedMethod = function(){};
}
}
obj = new MyObject();
myNestedObj1 = new obj.MyNestedObject;
I think you should omit new in nested object. It should be simple function:
function MyObject(){
this.myProp;
this.myMethod = function(){};
this.MyNestedObject = function(){ //no need of `new`
this.myNestedProp = 5;
this.myNestedMethod = function(){};
}
}
obj = new MyObject();
myNestedObj1 = new obj.MyNestedObject(); //better user brackets here too
myNestedObj2 = new obj.MyNestedObject();
myNestedObj3 = new obj.MyNestedObject();
You will be declaring nested object (or if you prefer OOP terminology then nested class) as a simple function, which when you call with new acts as a constructor resolving any this references inside the function pointing to newly constructed object. Thus essentially when you call **new** obj.MyNestedObject();
this.myNestedProp = 5;
adds myNestedProp property on newly created object (or this object). Similarly,
this.myNestedMethod = function(){};
adds myNestedMethod function on newly created object (or this object).
If you omit new in
myNestedObj1 = new obj.MyNestedObject();
Then MyNestedObject() will be invoked in the context of MyObject(). Thus this inside obj.MyNestedObject() will point to MyObject(). Thus before the execution of this above line, both MyObject() and obj will have three members: myProp, myMethod and MyNestedObject, but after execution of this call, it will add myNestedProp and myNestedMethod to the definition of MyObject() which in turn also appear inside obj.
Related
i'm new to JS and got the following problem:
Why is this not working / what is this code doing?
var Test = {};
Test.prop = "test property";
Test.Class1 = function () {
}
Test.Class1.prototype = {
m1: function() {
console.log(this.prop);
}
}
Test.Class1.m1();
My understanding of this code would be:
creating a new object called Test
adding the property prop to Test
creating a new object called Class1 in Test
adding a method m1 to Class1
calling the m1 method of Class1 in Test
In JavaScript, even the prototype property of a function is an object. Prior to creating an object whose prototype is the one you've defined, Test1.Class1.prototype is just a regular object. Basically it works the same way as the following code snippet:
var Test1 = { prototype { m1: function() {} } };
// You're trying to call an undefined function!
Test.m1();
// This is fine
Test1.prototype.m1();
In the other hand, when you use the new operator, you're creating a new object whose prototype is the one set to the constructor function. And here starts the magic:
var Test1 = function() {};
Test1.prototype = {
doStuff: function() {}
};
var object1 = new Test1();
// This works!
object1.doStuff();
When you access a property, JavaScript's runtimes inspect the object to find out if there's a function called doStuff, otherwise it looks for it on the object's prototype, otherwise it looks on the prototype of the prototype and so on...
Actually new operator is a syntactic sugar. ECMA-Script 5 introduced Object.create which makes everything more clear:
var Test1 = {
doStuff: function() {
}
};
// The first parameter of Object.create is
// the object that's going to be the prototype of
// Test1 object!
var object1 = Object.create(Test1);
// This works too!
object1.doStuff();
Probably you should check this other Q&A: How does JavaScript .prototype work?
You need to create an instance of the prototype before you're able to use its methods:
var instance = new Test.Class1();
console.log(instance.m1());
Even as such, Test.prop is not part of the instance, and will not be accessible to m1
Edit: Here's a working example:
var test = function() {
this.prop = "A property";
}
test.prototype.m1 = function() {
console.log(this.prop);
}
var instance = new test();
console.log(instance.m1());
prototype chaining only works for instances created with the new operator.
Otherwise you will have to explicitly call prototype to access the method.
let testClass = new Test.Class1();
testClass.m1();
Also since you are trying to access the prop property.
Test.Class1.prototype = {
m1: function() {
console.log(this.prop);
}
}
The call site is Test.Class1, the prop should be part of Test.Class1 and not on Test
I changed up the names of things, but this should work.
var Person = function(){
this.message = "Hello, world!";
};
Person.prototype = Object.create(Object.prototype);
Person.prototype.constructor = Person;
Person.prototype.greet = function(){
console.log(this.message);
alert(this.message);
};
var tom = new Person();
tom.greet();
What is the harm in copying the prototype of a function to another function like shown below.
function Person(){}
Person.prototype = {};
function Author(){}
Author.prototype = Person.prototype;
Object assignments in JS create a reference.
var o = {};
var c = o;
Now both the objects o and c are referring to the same object. Same rule applies when trying to assign the prototype of one object to another.
Author.prototype = Person.prototype;
Now the prototypes of both Author and Person refers to a single object. If you put some data to a prototype property of the Author, the same data will be there for the Person too. This is least expected for distinct objects.
One of the proper ways of doing this is
Author.prototype = Object.create(Person.prototype);
Here you create a brand new object for Author.prototype - but inheriting from Person object.
Because you're passing the prototype by reference, which means both are affected by all changes. Consider:
function Person(){}
Person.prototype = {};
function Author(){}
Author.prototype = Person.prototype;
Author.prototype.books = [];
var bob = new Person();
console.log(bob.books); // this will be an empty array, not undefined as one would expect.
The Ideal way of attaching methods to prototype is by creating an object which is created by instance.
function Person(){
this.test = "1";
}
function Author(){}
Author.prototype = new Person();
this way you create a new instance of person and returned object is fed into Author.
What if you simply copy it ?
If you simply copy the same instance is shared across prototypes , change in one prototype will be reflected in all.
function b(){
this.test = 'a';
this.test1 = function(){
console.log('test1');
}
this.test2 = function(){
console.log('test2');
}
}
function a(){
}
function c(){
}
a.prototype = new b();
var a1 = new a();
c.prototype = a.prototype;
a.test = 'asdf';
console.log(c.test);
Uniqueness of data to an instance will be missing.
I have an object that looks like
var customObject = function() {
this.property = "value";
};
customObject.prototype = new otherObject();
customObject.prototype.property2 = function() {};
etc. - it's much bigger than this.
I can successfully instantiate the object by writing new customObject().
Now I would like to create a rather similar object, although a little different. This involves modifying certain properties and perhaps even adding or removing some. As in the above example, I would like it to be invokable by writing new customObject2().
I thought I could simply do:
var customObject2 = new customObject();
customObject2.prototype = customObject.prototype;
customObject2.property = "modified value";
etc.
However, when I try to instantiate it by doing new customObject2() I receive an error, stating that the customObject2 is not a function.
I hope I could illustrate well enough as to what pattern I desire to create. What approach should I take to create such a pattern?
If customObject is not a host object (i.e. won't give you an illegal invocation error if you try to call it differently to expected) you can apply the constructor to a different this Object;
var customObject2 = function () {
customObject.call(this); // construct as if `customObject`
// now do more stuff
this.anotherProperty = 'foo';
};
customObject2.prototype = Object.create(customObject.prototype);
// inherit prototype but keep original safe
new customObject2();
Backwards compatible Object.create
function objectWithProto(proto) {
var f;
if (Object.create) return Object.create(proto);
f = function () {};
f.prototype = proto;
return new f();
}
I think this should answer your question. Basically, the new keyword is returning an object and not a function.
Why are you not using the same formula you used the first time? For example:
var customObject2 = function(){};
customObject2.prototype = new customObject();
customObject2.property = "modified value";
new customObject2(); // works!
All properties of customObject will be inherited by the instances of customObject2 through the prototype chain.
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 overwrite the Object constructor:
function Object() {
console.log("here");
}
when I call var x = new Object();, I can see "here".
However, when I call var x = {};, I can't got it.
Isn't {} the same as new Object()? How can I get this work?
using object() creates new function with name object with scope on document object, actually does not override object. While using var x = {}, it use original JS object.