javascript calling the function from prototype - javascript

I am learning javascript. When I call pictureArrayAdd method I receive error Picture.pictureArrayAdd is not a function. Why?
window.onload = init;
//window.picture = new Array();
function init() {
var button = document.getElementById("addButton");
button.onclick = addPicture;
}
function Picture() {};
Picture.prototype = {
pictureArray: [],
pictureArrayAdd: function(newImage) {
this.pictureArray.push(newImage);
return this
}
}
var addPicture = function() {
var textInput = document.getElementById ("pictureName");
var newPicture = textInput.value;
Picture.pictureArrayAdd(newPicture);
}

You have to initialize an instace of your object:
var addPicture = function() {
var textInput = document.getElementById ("pictureName");
var newPicture = textInput.value;
var pic = new Picture();
pic.pictureArrayAdd(newPicture);
}
Besides - just a tip -, you can use a optional parameter on your constructor, like this:
function Picture(newImage) {
if (newImage != undefined) {
this.pictureArrayAdd(newImage);
}
};
So you have a shortcut to your pictureArrayAdd function:
var pic = new Picture("picture1.png");
See it working here.

Related

How to get a JavaScript "class" by invoking "new" from another "class"?

We can define a "class" In JavaScript by function, and get its "instance" by the "new" command. Just as follows:
function class_a() {
this.tell = function () {
console.log("This is a_class");
}
}
function class_b() {
this.tell = function () {
console.log("This is b_class");
}
}
var instance_a1 = new class_a();
var instance_b1 = new class_b();
instance_a1.tell();
instance_b1.tell();
My question is: Is there a way to generate these "classes" by the new command from another class? Just like this:
function typex(class_name)
{
...
}
var myclass_a = new typex("class_a");
var myclass_b = new typex("class_b");
var instance_a1 = new myclass_a();
var instance_b1 = new myclass_b();
instance_a1.tell();
instance_b1.tell();
Return the classes from typex but just as reference to the function itself (no invoking inside typex).
Option A: Private classes
function typex(class_name)
{
function class_a() {
this.tell = function () {
console.log("This is a_class");
}
}
function class_b() {
this.tell = function () {
console.log("This is b_class");
}
}
if (class_name === "class_a")
return class_a;
if (class_name === "class_b")
return class_b;
throw new Error("unrecognized classname");
}
Option B: Public classes
function class_a() {
this.tell = function () {
console.log("This is a_class");
}
}
function class_b() {
this.tell = function () {
console.log("This is b_class");
}
}
function typex(class_name)
{
if (class_name === "class_a")
return class_a;
if (class_name === "class_b")
return class_b;
throw new Error("unrecognized classname");
}
Then running the code:
var myclass_a = new typex("class_a");
var myclass_b = new typex("class_b");
var instance_a1 = new myclass_a();
var instance_b1 = new myclass_b();
instance_a1.tell();
instance_b1.tell();
Creates for both the output
This is a_class
This is b_class
Firstly, I end up NOT using the keyword new when calling typex(...), bc I don't want whatever new typex(...) evalutes to to delegate its failed property lookups to typex.prototype.
Secondly, I capitalized MyClass_A and MyClass_B to indicate that they should be paired with the keyword new.
You could just have typex return a constructor function if that is the extent of your use case of these classes/instances.
function typex(class_name) {
var classes = {};
classes.class_a = function() {
this.tell = function() {
console.log('This is a_class');
};
};
classes.class_b = function() {
this.tell = function() {
console.log('This is b_class');
};
};
return classes[class_name];
}
var MyClass_A = typex("class_a");
var MyClass_B = typex("class_b");
var instance_a1 = new MyClass_A();
var instance_b1 = new MyClass_B();
instance_a1.tell(); // "This is class_a"
instance_b1.tell(); // "This is class_b"
instance_a1.constructor === instance_b1.constructor; // false (which is good)
Here's a heavily refactored version that reuses as much code and reduces memory usage as possible.
function typex(class_name) {
var ClassConstructor = function() {
this.class_name = class_name;
};
ClassConstructor.prototype.tell = function() {
console.log('This is ' + this.class_name);
};
return ClassConstructor;
}
var MyClass_A = typex("class_a");
var MyClass_B = typex("class_b");
var instance_a1 = new MyClass_A();
var instance_b1 = new MyClass_B();
instance_a1.tell(); // "This is class_a"
instance_b1.tell(); // "This is class_b"
instance_a1.constructor === instance_b1.constructor; // false (which is good)

Namespace With New Instance On Each Call

I'm trying to create something similar to d3(ex: d3.select()) but much more simple and I need to have a new instance each time I call the namespace function. Is this possible and/or am I approaching this wrong?
var dom = new function () {
var Element = null;
this.select = function (query) {
Element = document.querySelector(query);
return this;
};
this.append = function (elem) {
Element.append(elem);
return this;
};
};
Desired use
var bodyelement = dom.select("body");
var p = dom.select("p");
You need to run some code each time you use the dom object. So if the dom object was a function, you could call it to get a new instance.
var dom = function () {
var Element = null;
var newdom = {};
newdom.select = function (query) {
Element = document.querySelector(query);
return this;
};
newdom.append = function (elem) {
Element.append(elem);
return this;
};
return newdom;
};
console.log(dom() === dom(), "(false means the instances are different)");
var dom = new function () {
var Element = null;
this.select = function (query) {
Element = document.querySelector(query);
return this;
};
this.append = function (elem) {
Element.append(elem);
return this;
};
// add a way of accessing the resulting Element
this.element = function() { return Element; }
};
console.log(dom.select("body").element());
console.log(dom.select("p").element());
<p>blah</p>

Can't have access to a variable using call in Javascript

I'm studying Javascript and learning how to use call. I created this script and I don't know why I can't have access to this variable Time.
var MyObject;
(function(MyObject) {
var Runner = (function() {
function Runner(time) {
this.time = time;
}
var myFunctionArray = [];
Runner.prototype.execute = function() {
myFunctionArray[0]();
}
Runner.prototype.newTest = function(index, execute) {
var test = function() {
return execute.call(this);
}
myFunctionArray.push(test);
}
return Runner;
})();
MyObject.Runner = Runner;
})(MyObject || (MyObject = {});
var myNewObj = new MyObject.Runner(1000); myNewObj.newTest('1', function() {
console.log(this.time) //output: undefined
});
So how can I get time value inside newTest function?
Issue is in newTest function
Runner.prototype.newTest = function(index, execute) {
var test = function() {
return execute.call(this);
}
myFunctionArray.push(test);
}
Here this is pointing to test and not Runner. You will have to save context in a variable and then set it in call.
Runner.prototype.newTest = function(index, execute) {
var self = this;
var test = function() {
return execute.call(self);
}
myFunctionArray.push(test);
}
.call + self
var MyObject;
(function(MyObject) {
var Runner = (function() {
function Runner(time) {
this.time = time;
}
var myFunctionArray = [];
Runner.prototype.execute = function() {
myFunctionArray[0]();
}
Runner.prototype.newTest = function(index, execute) {
var self = this;
var test = function() {
return execute.call(self);
}
myFunctionArray.push(test);
}
return Runner;
})();
MyObject.Runner = Runner;
})(MyObject || (MyObject = {}));
var myNewObj = new MyObject.Runner(1000);
myNewObj.newTest('1', function() {
console.log(this, this.time) //output: undefined
});
myNewObj.execute()
.bind
As commented, you can even use .bind
var MyObject;
(function(MyObject) {
var Runner = (function() {
function Runner(time) {
this.time = time;
}
var myFunctionArray = [];
Runner.prototype.execute = function() {
myFunctionArray[0]();
}
Runner.prototype.newTest = function(index, execute) {
myFunctionArray.push(execute.bind(this));
}
return Runner;
})();
MyObject.Runner = Runner;
})(MyObject || (MyObject = {}));
var myNewObj = new MyObject.Runner(1000);
myNewObj.newTest('1', function() {
console.log(this, this.time) //output: undefined
});
myNewObj.execute()
When you declare your Runner function, you've actually declared a function that takes no arguments that then itself declares a function called Runner that takes one argument.
Actually In this code snippet :
Runner.prototype.newTest = function(index, execute) {
var test = function() {
return execute.call(this);
}
myFunctionArray.push(test);
}
this will reference to test variable (as per constructor invocation pattern)
So, to pass right variable cache the value of this in another variable and then pass that to function.

How to change the properties with factory method in javascript

i have one class i am trying to overwrite it with factory design pattern but not able to do that..
how to call it exactly to change the properties of object
function othername() {
var newobj = new Object();
newobj.fname = "sachin",
newobj.lname = "rawal",
newobj.fullname = function () {
alert(this.fname);
}
return newobj
}
var othername1 = othername ("hi","hello");
Using prototype you can do it.
function othername() {
var newobj = new Object();
newobj.fname = "sachin",
newobj.lname = "rawal",
newobj.fullname = function () {
alert(this.fname);
}
return newobj
}
var othername1 = othername ("hi","hello");
prototype:
othername.prototype.middleName = "middleNameString";
var named = othername();
var md = named.middleName // md == "middleNameString"
function Othername(fname,lname) {
this.fname = fname || "sachin";
this.lname = lname || "rawal";
};
Othername.prototype.fullname = function (){
alert(this.fname + " " + this.lname);
};
var othernameDefault = new Othername (); //sachin rawal
var othername1 = new Othername ("hi","hello"); //hi hello

How to "new" a returned function in Javascript

I am trying to simulate a namespace feature in Javascript.
var com = {};
com.domain = {};
com.domain.system = {};
com.domain.net = {};
com.domain.net.ip = {};
com.domain.net.ip.tcp = {};
com.domain.net.ip.udp = {};
com.domain.net.ip.ssl = {};
com.domain.util = {};
com.domain.util.timer = {};
com.domain.plugins = {};
com.domain.session = {};
com.domain.io = {};
com.domain.algorithm = {};
com.domain.debug = {};
This is the namespaces declaration. Later I will add functions to these namespaces.
This is my selector function:
For a convenient way to use namespaces, I add a function named $. This function will walk all namespaces in com. If the selected name exists, return the object.
function $ (selector) {
function digger (namespace, selector) {
for (var prop in namespace) {
if (typeof namespace[prop] == "array" || typeof namespace[prop] == "object") {
if (prop == selector) {
return namespace[prop];
}
var dig = digger(namespace[prop], selector);
if (dig != null) {
return dig;
}
} else {
if (prop == selector) {
return namespace[prop];
}
}
}
}
return digger (com, selector);
}
After that, I add a timer to namespace com.doamin.util.
com.domain.util.timer = function () {
this._handle = new InnerObj.SystemTimer(io);
return this;
};
com.domain.util.timer.prototype.expiresFromNow = function (seconds, cbHandler) {
this._handle.ExpiresFromNow (seconds, cbHandler);
};
com.domain.util.timer.prototype.wait = function (seconds, cbHandler) {
this._handle.Wait (seconds, cbHandler);
};
com.domain.util.timer.prototype.expiresAt = function (seconds, cbHandler) {
this._handle.Wait (seconds, cbHandler);
};
com.domain.util.timer.prototype.cancel = function () {
this._handle.Cancel ();
};
Usage:
1. var timer = new com.domain.util.timer (); OK
timer.expiresAt (1, {}); OK
2. var func = $("timer"); OK
var timer = new func (); OK
timer.expiresAt (1, {}); OK
But but but but but
var timer = new $("timer") (); NG
Can anyone tell me why the last new function is not working?
Try var timer = new ($("timer"))();.
Your question is not clear but I guess since $("timer") returns a function, you want a new instance of the result of $("timer") and not a new instance of $().

Categories

Resources