JavaScript - Meaning of: var DndUpload = function (inputElem){}; - javascript

Can I kindly ask for explanation:
What does the code below represent? Does it create a DndUpload Ojbect? Or, does it create a DndUpload() function? What I miss is the statement new normally present during JavaScript objects creation. Can I kindly ask for some explanation, as I am confused.
var DndUpload = function (inputElem)
{
this.input = inputElem;
this.dropZone = null;
this.isDragging = false;
this.init();
};
As far as I know this is the way to create object in Javascript:
var myObject = new function()
{
};
If you have any link with explanation, that would help. Thank you.

It's a worse way of writing this:
function DndUpload(inputElem)
{
this.input = inputElem;
this.dropZone = null;
this.isDragging = false;
this.init();
}
which is a function declaration. It does not create an instance of DndUpload. Technically, it does create an object – its name is DndUpload and it is an instance of Function. To create an instance of this "class:"
var instance = new DndUpload(document.getElementById('someInputId'));

var myObject = new function()
{
};
Defines an anonymous constructor function and then instantiates a new object using the anonymous constructor function. It could have been replaced with var myObject = {}.
var DndUpload = function (inputElem)
{
this.input = inputElem;
this.dropZone = null;
this.isDragging = false;
this.init();
};
Defines a constructor function (technically an anonymous constructor function assigned to a variable). You can then create objects of this "class" by invoking the constructor function with new:
var dndUploadObject = new DnDUpload(),
anotherUploadObject = new DnDUpload(); //2 unique DnDUpload objects

the code you have essentially creates a constructor for a "class" it's more or less a blueprint for an object.
It then puts that constructor into a variable called DndUpload
So you can now make an object with
var myObject = new DndUpload(input elem)

Related

Javascript prototype method "Cannot set property"

I'm always getting Cannot set property 'saySomething' of undefined but why?
Am I making a mistake somewhere?
var Person = new Object();
Person.prototype.saySomething = function ()
{
console.log("hello");
};
Person.saySomething();
Debugging tip: You get this ..of undefined errors when you try to access some property of undefined.
When you do new Object(), it creates a new empty object which doesn't have a prototype property.
I am not sure what exactly are we trying to achieve here but you can access prototype of function and use it.
var Person = function() {};
Person.prototype.saySomething = function() {
console.log("hello");
};
var aperson = new Person();
aperson.saySomething();
The prototype property exists on functions, not on instantiated objects.
var Person = new Object();
console.log(Person.prototype); // undefined
var Person2 = function () {}
console.log(Person2.prototype); // {}
This is useful because things put on the prototype of a function will be shared by all object instances created with that function (by using new).
var Person = function() {};
Person.prototype.saySomething = function() {
console.log("hello");
};
console.log(
new Person().saySomething === Person.prototype.saySomething // true. they are the same function
);
If all you want is to add a method to the person object, there's no need for a prototype:
var Person = {};
Person.saySomething = function() {
console.log("hello");
};
Person.saySomething();
You can even use object literal syntax:
var Person = {
saySomething: function() {
console.log("hello");
}
};
Person.saySomething();
i was trying out some code thought of posting it, might help others.
<script>
var MODULE = {};
MODULE = (function (my) {
my.anotherMethod = function () {
console.log("hello ");
};
my.newMethod = function(){
console.log("hi new method ");
}
return my;
}(MODULE));
MODULE.anotherMethod();
MODULE.newMethod();
</script>
And please not var MODULE ={}, if this is not initialized with {} then it give cannot set property.
I know i am late to the party but as you see there is no satisfying answer available to the question so i am providing my own.
In your case when you write
var Person = new Object();
you are creating an instance of Object type.
You can add a property using prototype property to the Object, not to the instance of Object.which you can use by the instance laterly.
so you can define like
Object.prototype.saySomething = function ()
{
console.log("hello");
};
now you can call it like this.
Person.saySomething();
You can check here.
var Person = function(name) {
this.canTalk = true;
this.name = name;
};
Person.prototype.greet = function() {
if (this.canTalk) {
console.log('Hi, I am ' + this.name);
}
};
bob = new Person('bob');
bob.greet();

Object doesn't inherit parent object functions

I have some functions defined inside an object:
var functions = {
__construct: function(){
console.log(this);
this.prototype.__construct(); // <problem
}
};
I merge this object with another one that is a function (after I create a new instance of the function):
var plugin = function(){};
plugin.prototype.__construct = function(){
console.log('parent');
};
var i = new plugin();
i = $.extend({}, i, functions);
But after that when I try to call the __construct function:
i.__construct();
I get this error:
Uncaught TypeError: Cannot call method '__construct' of undefined
It's because this line:
this.prototype.__construct();
I tried to see if I can call the parent constructor function from the child constructor, but it appears that the object doesn't have a prototype? wtf?
Not sure what you're trying to do here but i does have a __construct function when using the code you provided:
var functions = {
__construct: function(){
console.log(this);
this.prototype.__construct(); // <problem
}
};
var plugin = function(){};
plugin.prototype.__construct = function(){
console.log('parent');
};
var i = new plugin();
i = $.extend({}, i, functions);
console.log(i.__construct===functions.__construct);//true
console.log(i.__construct===plugin.prototype.__construct);//false
Not sure what you think this.prototype is going to be, maybe this answer will clear up what prototype is used for (shared members) and what this means (instance specific). You can shadow shared members that are defined in the prototype further down the prototype chain or in an instance but that's not what you're doing here.
If you dynamically want to extend an instance created with a constructor function you can do something like this:
var functions = {
__construct: function(){
this.constructor.prototype.__construct.call(this);
}
};
var Plugin = function(){};
Plugin.prototype.__construct = function(){
console.log('parent');
};
var i = new Plugin();
i = $.extend(i,functions);
i.__construct();

instantiating more than one object

in Javascript, I am creating an object like this:
var testObject = {
value: "this is my initial value",
setup: function() {
value: "foo"
}
};
Now, I would like to be able to instantiate this object, so I am trying this:
var myFirstObject = new testObject();
var mySecondObject = new testObject();
so that when I call .setup() it will change the value only for that referenced newly created object. How can I achieve this? This code does not seem to work.
You don't instantiate objects, you instantiate functions.
var testObject = function() {
this.value = "this is my initial value";
this.setup = function() {
this.value = "foo";
}
}
var myFirstObject = new testObject();
var mySecondObject = new testObject();
EDIT:
As per your comment, here's how you would bind to the DOM using functions on this object:
document.getElementById('idOfElem').addEventListener(
'click', myFirstObject.clickHandler);
Bear in mind that you won't have any guarantee that the click handler will be executed in the context of your object (i.e. in your click handler, this might not be your testObject instance). If your clickHandler intends to modify the object's instance variable in any way, it's better to ensure the context like so:
document.getElementById('el').addEventListener('click',
function() {
myObj.handleClick.apply(myObj, arguments);
});
You have numerous problems with your code. Firstly, you are trying to instantiate something, by calling a constructor function. Your testObject is not a function, so you'll cause a type error. You need to change testObject to be something along these lines:
var TestObject = function () {
this.value = "this is my initial value";
};
TestObject.prototype.setup = function () {
this.value = "foo";
};
Notice that I've used an uppercase T in that identifier... that's just best practice for a constructor function. Also notice how I've defined the setup method on the prototype. This is much more efficient than defining it as a property of the instance (with this.setup) since only one copy of the function needs to exist in memory.
Now that TestObject is a function it can be instantiated by calling it with the new operator:
var myFirstObject = new TestObject();
var mySecondObject = new TestObject();
When you call the setup method on an instance of TestObject, it will apply to that instance. In other words, the value of this inside the setup method will refer to the instance on which the method has been called:
myFirstObject.setup();
console.log(myFirstObject.value); // 'foo'
console.log(mySecondObject.value); // 'this is my initial value'
You have incorrectly defined your constructor. Try this:
function testObject() {
this.value = "this is my initial value";
this.setup = function() {
this.value = "foo"
}
};
You can then call new testObject().
The object notation your using is something you can compare with a static class.
Here is the code for what you're trying to achieve:
var testObject = function(val) {
this.value = "This is my initial value",
if (arguments[0]) {
this.value = val;
}
};
var first = new testObject(); //uses initial value
var second = new testObject("hi"); //value = hi
If you'd like to write classes using this notation take a look at this: http://ejohn.org/blog/simple-javascript-inheritance/
function yourObject(value, setup) {
return {
value: value,
setup: setup
};
}
var myFirstObject = new yourObject('a', function(){});
var mySecond = new yourObject('b', function(){});

Static/shared property and method in JavaScript

I'm trying to have a 'class' in JS which tracks how many instances of itself have been instantiated. I am attempting to do so like this...
var myNamespace = {};
myNamespace.myClass = function () {
//fails here as .getNetInstanceNo() not recognised...
var instanceNumber = myNamespace.myClass.getNextInstanceNo();
return {
instanceNo : function() { return instanceNumber; }
}
};
myNamespace.myClass.InstanceNo = 0; //static property?
//should the class itself have this method added to it...
myNamespace.myClass.prototype.getNextInstanceNo = function () { //static method?
return myNamespace.myClass.InstanceNo++;
};
var class1 = new myNamespace.myClass();
alert('class 1 has instance of ' + class1.instanceNo() );
However this fails as the getNextInstanceNo function is not recognised. Even though I think I'm adding it through the myClass.prototype.
What am I doing wrong?
prototype is an object from which other objects inherit properties, as in when you create an instance of an object and that object doesn't have a property/method, when called, the prototype of the class in which the object belongs to is searched for that property/method, here's a simple example:
function Animal(){};
Animal.prototype.Breathe = true;
var kitty= new Animal();
kitty.Breathe; // true (the prototype of kitty breathes)
var deadCat = new Animal();
deadCat.Breathe = false;
deadCat.Breathe; // false (the deadCat itself doesn't breath, even though the prototype does have breath
As you said yourself, you don't need to define getNextInstanceNo on prototype, since that's not how static methods are defined on JavaScript, leave it right right there on the class itself, instead you can define the instanceNo method on prototype, here's how:
var myNamespace = {};
myNamespace.myClass = function () {
this.instanceNumber = myNamespace.myClass.getNextInstanceNo();
};
myNamespace.myClass.prototype.instanceNo = function () {
return this.instanceNumber;
};
myNamespace.myClass.InstanceNo = 0;
myNamespace.myClass.getNextInstanceNo = function () {
return myNamespace.myClass.InstanceNo++;
};
var class1 = new myNamespace.myClass();
alert('class 1 has instance of ' + class1.instanceNo());

Javascript - Create instance with array of arguments

I know the possibility to call a function with an array of arguments with apply(obj,args);
Is there a way to use this feature when creating a new instance of a function?
I mean something like this:
function A(arg1,arg2){
var a = arg1;
var b = arg2;
}
var a = new A.apply([1,2]); //create new instance using an array of arguments
I hope you understand what i mean... ^^^
Thanks for your help!
Solved!
I got the right answer. To make the answer fit to my question:
function A(arg1,arg2) {
var a = arg1;
var b = arg2;
}
var a = new (A.bind.apply(A,[A,1,2]))();
var wrapper = function(f, args) {
return function() {
f.apply(this, args);
};
};
function Constructor() {
this.foo = 4;
}
var o = new (wrapper(Constructor, [1,2]));
alert(o.foo);
We take a function and arguments and create a function that applies the arguments to that function with the this scope.
Then if you call it with the new keyword it passes in a new fresh this and returns it.
The important thing is the brackets
new (wrapper(Constructor, [1,2]))
Calls the new keyword on the function returned from the wrapper, where as
new wrapper(Constructor, [1,2])
Calls the new keyword on the wrapper function.
The reason it needs to be wrapped is so that this that you apply it to is set with the new keyword. A new this object needs to be created and passed into a function which means that you must call .apply(this, array) inside a function.
Live example
Alternatively you could use ES5 .bind method
var wrapper = function(f, args) {
var params = [f].concat(args);
return f.bind.apply(f, params);
};
See example
with ECMAscript 5 you can:
function createInstanceWithArguments (fConstructor, aArgs) {
var foo = Object.create(fConstructor.prototype);
fConstructor.apply(foo, aArgs);
return foo;
}
#Raynos answer works well, except that the non-ES5 version is missing the constructor's prototype after instantiation.
Here's my updated cApply method:
var cApply = function(c) {
var ctor = function(args) {
c.apply(this, args);
};
ctor.prototype = c.prototype;
return ctor;
};
Which can be used like this:
var WrappedConstructor = cApply(Constructor);
var obj = new WrappedConstructor([1,2,3]);
// or inline like this.
var obj2 = new (cApply(Constructor))([1,2,3]);
JSFiddle for reference.
You can curry the functions:
function A(arg1, arg2) {
// ...
}
function A12() {
A(1, 2);
}
You could even build a curry factory:
function A_curry() {
var args = arguments;
return function () {
A.apply(null, args);
};
}
You can use Object.create() to build the new instance, and call the constructor on the instance after that:
var args = [1,2,3];
var instance = Object.create(MyClass.prototype);
MyClass.apply(instance, args);
or in a single line:
var instance = MyClass.apply(Object.create(MyClass.prototype), args);
but don't forget return this; in MyClass by this single line solution.
If you don't have Object.create(), then it is very simple to write one:
Object.create = function (source){
var Surrogate = function (){};
Surrogate.prototype = source;
return new Surrogate();
};
You can optionally write an Function.newInstance() or a Function.prototype.newInstance() function:
Function.newInstance = function (fn, args){
var instance = Object.create(fn.prototype);
fn.apply(instance, args);
return instance;
};
so var instance = Function.newInstance(MyClass, args);.
note: It is not recommended to override native classes.
What if you have your object class name stored in a variable called className ?
var className = 'A'
According to this answer here it all becomes very clean and simple using ECMAScipt5's Function.prototype.bind method.
With an array of arguments:
new ( Function.prototype.bind.apply( className, arguments ) );
Or with an argument list:
new ( Function.prototype.bind.call( className, argument1, argument2, ... ) );
A single line, no need for a wrapper.
I just had the same issue and also wanted to preserve prototype properties of the target object. After looking at the answers, just came up with a rather simple solution. Thought I might as well share it for any future seeker :)
// Define a pseudo object that takes your arguments as an array
var PseudoObject = function (args) {
TargetObject.apply(this, args);
};
// if you want to inherit prototype as well
PseudoObject.prototype = new TargetObject();
// Now just use the PseudoObject to instantiate a object of the the OtherObject
var newObj = new PseudoObject([1, 2, 3]);
It can now be done using the spread operator:
let a = new A(...[1,2]);
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Spread_syntax#examples

Categories

Resources