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
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)
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>
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.
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
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 $().