I am new to Javascript. I have defined an object using object initializer method.
var obj = { a : "A";
b : "B";
myFunc = function() {
alert("Hello"):
}
Now I want to create another object that will be child of Obj. How can I do that.
var obj1 = new obj();
is not working.
First off, you have a syntax error with
myFunc = function() { ...
Anyway, this is how you'll want to set it up
function Foo() {
this.a = "A";
this.b = "B";
}
Foo.prototype.myFunc = function() {
alert("hello");
};
Now to create your child object
function Bar() {
Foo.call(this); // call parent constructor; optional
}
// setup child prototype
Bar.prototype = Object.create(Foo.prototype);
Bar.prototype.constructor = Bar;
Check it out
var b = new Bar();
b instanceof Bar; // true
b instanceof Foo; // true
b.constructor.name; // Bar
b.myFunc; // "hello"
To do it the way you wanted to:
var obj = {
a: "A",
b: "B",
myFunc: function () {
alert("Hello");
}
};
var obj1 = Object.create(obj)
obj1.a = 2;
console.log(obj1);
console.log(obj);
Related
let bar;
function foo(){
this.x=x;
this.y=y;
}
bar=new foo(1,2);
/*Since all functions in javascript are objects.
Why can't an instance an object be a constructor itself?*/
!function bar(a,b){
this.a=a;
this.b=b;
}(); // (1)
let bar1=new bar(3,4);
console.log(bar1.a);
(1): Using a named IIFE, can bar be an instance and a constructor at the same time?
It's just a fun trick to exploit the language's freedom to see if it is a possibility, any other ways of doing this?
It sounds like you are looking for a constructor-function-returning function:
function makeBar(x, y) {
function Bar(a, b) {
this.a = a;
this.b = y + b;
}
Bar.x = x;
return Bar;
}
var Bar1 = makeBar("bar1", 2);
console.log(Bar1.x); // "bar1"
var myBar1 = new Bar1(1, 2); // Bar { a: 1, b: 4 }
console.log(myBar1 instanceof Bar1); // true
var Bar2 = makeBar("bar2", 0);
var myBar2 = new Bar2(3, 3); // Bar { a: 3, b: 3 }
console.log(myBar2 instanceof Bar1); // false
To make makeBar not a factory function but a constructor with a working prototype, you'd have to use
function Foo(x, y) {
function Bar(a, b) {
this.a = a;
this.b = y + b;
}
Object.setPrototypeOf(Bar, Foo.prototype);
Bar.x = x;
return Bar;
}
Foo.prototype.log = function() {
console.log("I'm "+this.name);
};
var Bar = new Foo("bar", 2);
Bar.log();
console.log(Bar instanceof Foo); // true
var myBar = new Bar(1, 2);
console.log(myBar instanceof Bar); // true
Can a JavaScript instance be a constructor itself & have its own set of instances?
Sure, a function is an instance of Function and a constructor is a function.
So you can just have
const instance1 = new Function("a", "this.a = a;");
const instance2 = new instance1("foo");
console.log(instance2.a); // "foo"
If you need instance1 to be more than a raw Function, you can even extend this constructor:
class MyFunc extends Function {
doSomethingMore(){ console.log("I'm doing more"); }
}
const instance1 = new MyFunc("a", "this.a = a;");
instance1.doSomethingMore();
const instance2 = new instance1("foo");
console.log(instance2.a); // "foo"
But I can't see a clear reason why you'd ever want to do that...
(Note that dynamically creating a function via the Function constructor is generally less "performant" than at parse time through function expression or statement.)
In your code, since bar is declared with let, it can't be re-declared as a function declaration in the same scope.
If you wanted to do this, you could have foo explicitly return a function, which could then be called with new:
function foo(x, y) {
this.x = x;
this.y = y;
return function bar(a, b) {
this.a = a;
this.b = b;
};
}
const bar = new foo(1, 2);
const bar1 = new bar(3, 4);
console.log(bar1.a);
My goal is to have otherFoo inherit from foo, but then not inherit back up to the parent. I've tried a few angles with Object.create but it keeps inheriting back to the parent.
var foo = { "bar": {"data1":"02", "data2":"03"}, "otherBar":"09"};
var otherFoo = {};
otherFoo.bar = foo.bar;
otherFoo.bar.data1 = "04";
I want the end result to be
// foo = { "bar": {"data1":"02", "data2":"03"}};
// otherFoo = { "bar": {"data1":"04", "data2":"03"}};
Here is a JSFiddle for Convenience
Do you mean Object.assign() ?
let foo = { "bar": {"data1":"02", "data2":"03"}, "otherBar":"09"};
let otherFoo = Object.assign({}, foo);
foo.otherBar = 10;
console.log(foo);
console.log(otherFoo);
You could try using a class:
function template(data1) {
this.data = { "bar": {"data1": typeof data1 !== 'undefined' ? data1: '02', "data2":"03"}};
}
var foo = new template();
var otherFoo = new template('04');
console.log(foo.data);
console.log(otherFoo.data);
Close to Talha's answer, but figured i'd just go ahead and post it (as it mimicks your example almost exactly above on what you want the data represented like)
const bar = function(data){
this.bar = data;
}
let foo = new bar({"data1":"02", "data2":"03"})
let otherFoo = new bar({"data1":"04", "data2":"03"})
console.log(foo)
console.log(otherFoo)
If you can use Object spread operator:
var foo = { "bar": {"data1":"02", "data2":"03"}, "otherBar":"09"};
var { otherBar, ...bar } = foo
foo = bar
var fooBar = {
bar: { ...foo.bar, data2: "04" }
}
Otherwise you need a deep clone of your object.
Here's a function that can deep clone any object, including cyclical objects. It also maintains cyclical references as they are in the original object, without referencing any values from the original, except for values in the prototype chain:
function clone (object, objects = new WeakMap()) {
// this will omit copying primitives
if (typeof object !== 'object' && typeof object !== 'function' || object === null) {
return object;
}
if (objects.has(object)) {
return objects.get(object);
}
const proto = Object.getPrototypeOf(object);
const descriptors = Object.getOwnPropertyDescriptors(object);
const copy = typeof object === 'function'
? object.call.bind(object)
: Object.create(proto);
objects.set(object, copy);
Object.values(descriptors).forEach(descriptor => {
if ('value' in descriptor) {
descriptor.value = clone(descriptor.value, objects);
}
});
return Object.defineProperties(copy, descriptors);
}
let foo = { bar: { data1: '02', data2: '03' }, otherBar: '09' };
class Test {
constructor (...args) { this.args = args; }
cool () { return 'feature'; }
}
foo.bar.foo = foo;
foo.bar.bar = foo.bar;
foo.test = new Test('foo', 'bar');
foo.bar.test = foo.test;
foo.bar.func = () => 'func';
console.log(foo);
var otherFoo = clone(foo);
// everything copies as expected
console.log(otherFoo);
console.log(otherFoo.test instanceof Test);
console.log(otherFoo.bar.func() === 'func');
console.log(typeof otherFoo.bar.func === 'function');
// nothing references the original object
console.log(foo !== otherFoo);
console.log(foo.bar !== otherFoo.bar);
console.log(foo.test !== otherFoo.test);
console.log(foo.bar.func !== otherFoo.bar.func);
// doesn't copy prototypes
console.log(foo.test.cool === otherFoo.test.cool);
.as-console-wrapper{max-height:100%!important}
I have some code:
var obj = function() { }; // functional object
obj.foo = 'foo';
obj.prototype.bar = 'bar';
for (var prop in obj) {
console.log(prop);
}
What surprised me is that all that is logged is foo. I expected the for loop to iterate over the properties of the obj's prototype as well (namely bar), because I did not check for hasOwnProperty. What am I missing here? And is there an idiomatic way to iterate over all the properties in the prototype as well?
I tested this in Chrome and IE10.
Thanks in advance.
You're iterating over the constructor's properties, you have to create an instance. The instance is what inherits from the constructor's prototype property:
var Ctor = function() { }; // constructor function
Ctor.prototype.bar = 'bar';
var obj = new Ctor(); // instantiation
// adds own property to instance
obj.foo = 'foo';
// logs foo and bar
for (var prop in obj) {
console.log(prop);
}
If you want to maintain an inheritance hierarchy by defining all the properties even before the object instantiation, you could follow the below approach. This approach prints the prototype hierarchy chain.
Note: In this approach you don't have to create the constructor initially.
function myself() {
this.g = "";
this.h = [];
this.i = {};
myself.prototype = new parent();
myself.prototype.constructor = myself;
}
function parent() {
this.d = "";
this.e = [];
this.f = {};
parent.prototype = new grandParent();
parent.prototype.constructor = parent;
}
function grandParent() {
this.a = "";
this.b = [];
this.c = {};
}
var data = new myself();
var jsonData = {};
do {
for(var key in data) {
if(data.hasOwnProperty(key) && data.propertyIsEnumerable(key)) {
jsonData[key] = data[key];
}
}
data = Object.getPrototypeOf(data).constructor.prototype;
Object.defineProperties(data, {
'constructor': {
enumerable: false
}
});
} while (data.constructor.name !== "grandParent")
console.log(jsonData);
I read crockford's page on private members http://javascript.crockford.com/private.html in Javascript and got a question which maybe somewhat related. Why should a developer use Prototype?
For example,
For example, I can do this
var Foo = new Object();
Foo.bar = function() { alert('Its a bar'); };
var x = Foo;
x.bar();
instead of
var Foo = function(){};
Foo.prototype.bar = function(){alert('Its a bar');};
var x = new Foo();
x.bar();
Both of these implementations do the same thing. How is one different from the other? Does this affect inheritance in any way?
When you use the prototype pattern, only one instance of attributes you add to the prototype exist.
// Lets create 1000 functions which do the same thing
for (var i=0;i<1000;i++) {
Foo = new Object();
Foo.bar = function() { alert('Its a bar'); };
var x = Foo;
x.bar();
}
// This is the same as #1, but is more common
function Foo() {
this.bar = function () { alert('It\'s a bar'); };
}
for (var i=0;i<1000;i++) {
var x = new Foo;
x.bar();
}
// Lets create 1 function
var Foo = function(){};
Foo.prototype.bar = function(){alert('Its a bar');};
for (var i=0;i<1000;i++) {
var x = new Foo();
x.bar();
}
The prototype pattern has the disadvantage of not being able to access private members.
// Lets create 1 function
var Foo = function(){
var private = 4;
this.baz = function () {
alert(private);
}
};
Foo.prototype.bar = function(){alert(private);};
var x = new foo;
x.bar(); // error; `private` is undefined
x.baz(); // ok
I am trying to do something like this:
var test = {
a: 10,
b: 20,
c: (this.a+this.b)
};
but it doesn't work. How can I access the test.a from within test.c?
Is it possible?
It's not possible to reference "this" in an expression specifying an object literal. Either do it in a following line or use a constructor like this:
function myobj(a,b) {
this.a = a;
this.b = b;
this.c = this.a + this.b;
}
var test = new myobj(10,20);
In response to which method is faster, creation with the object constructor is faster. Here's a simple test case comparison. Run it yourself on JSBIN.
The results show that the object creation with a constructor vs an object literal is almost twice as fast:
0.450s : testObjectLiteral
0.506s : testObjectLiteralWithFunction
0.280s : testConstructor
Here's the test code inlined as well:
// timer function
function time(scope){
time.scope = time.scope || {};
if(time.scope[scope]) {
var duration = (new Date()).getTime()-time.scope[scope];
time.scope[scope] = null;
var results = document.getElementById("results");
results.innerHTML = results.innerHTML + '<p>'+(duration/1000).toFixed(3)+'s : '+scope+'</p>';
} else {
time.scope[scope] = (new Date()).getTime();
}
}
// object creation function with constructor
function myobj(a,b) {
this.a = a;
this.b = b;
this.c = this.a + this.b;
}
function testConstructor(iterations) {
var objs = new Array(iterations);
for(i=0;i<iterations;i++) {
objs[i] = new myobj(i,i+1);
}
return objs;
}
function testObjectLiteralWithFunction(iterations) {
var objs = new Array(iterations);
for(i=0;i<iterations;i++) {
objs[i] = {
a: i,
b: i+1,
c: function() {
return this.a + this.b;
}
};
}
return objs;
}
function testObjectLiteral(iterations) {
var objs = new Array(iterations);
for(i=0;i<iterations;i++) {
var item = {
a: i,
b: i+1
};
item.c = item.a + item.b;
objs[i] = item;
}
return objs;
}
var ITERATIONS = 1000000;
time("testObjectLiteral");
testObjectLiteral(ITERATIONS);
time("testObjectLiteral");
time("testObjectLiteralWithFunction");
testObjectLiteralWithFunction(ITERATIONS);
time("testObjectLiteralWithFunction");
time("testConstructor");
testConstructor(ITERATIONS);
time("testConstructor");
It's not possible within an object literal since this cannot be made to refer to an object that has not yet been created. Your best option is to assign the c property in a separate step:
var test = {
a: 10,
b: 20
};
test.c = test.a + test.b;
You simply can't do this when declaring an object literal, the closest you can do is:
var test = {
a: 10,
b: 20
};
test.c = test.a + test.b;
In your context this refers to whatever parent context you're in, not the test object...and even if it did, you can't declare members like that, for example this is also invalid:
var test = { a: 10, b: 20, test.c: test.a + test.b };
...because test, a and b aren't defined yet, since it's a single statement that hasn't completed.
Why not make c a function so that it always returns the current value of a+b?
var test = {
a: 5,
b: 1,
c: function() {
return this.a + this.b;
}
}