I initaialized the object method below, and it mysteriously cleared my object - javascript

I have this code snippet I made:
var SCP_Object = {
scp_function:function(){
var proxy_this={};
proxy_this.a = 5;
proxy_this.b = 7;
return proxy_this;
},
get scp_function(){
this.scp_function.random_string = "Hello, World!";
}
}
var new_SCP = new SCP_Object.scp_function();
When I ran it, I got RangeError: Maximum Call Stack Size Exceeded., and more curiously, new_SCP was undefined, and more curious still, SCP_Object was now an empty object {}.
What exactly happened here? I guess it enetered into a forever loop of sorts, but why did it clear the object?

Okay, so there are a few different things going on here! I'll work through each. First off, the new keyword/operator is reserved for JavaScript classes and functions. For this same reason, the below code will throw an error:
let A = {b:2};
new A();
// -> !!! Uncaught TypeError: A is not a constructor
I presume here that you would like to set up SCP_Object as a class and not just an ordinary object, but I'll deal with this as an object first and then move onto how to work with it as a class.
Getters and setters are perfectly legal to use on regular JavaScript objects, but there are three issues with yours:
new_SCP will not equal anything because your getter function does casually return anything.
Your getter function shares the same name as one of your scp_function property, which is illegal. Properties cannot share the same name as getter/setter functions.
You are calling the getter with parentheses as if it is a function (()), but it is not. You only need to call the property name of the getter and it will return whichever value you set it to return.
Let's resolve these issues:
var SCP_Object = {
_scp_function: function() {
var proxy_this = {};
proxy_this.a = 5;
proxy_this.b = 7;
return proxy_this;
},
get scp_function() {
var proxy_this = this._scp_function()
proxy_this.random_string = "Hello, World!";
return proxy_this;
}
}
var new_SCP = SCP_Object.scp_function;
console.log(new_SCP);
If you would like to achieve this with a class so you can use the new operator, we can do so like this:
class SCP_Object {
_scp_function() {
var proxy_this = {};
proxy_this.a = 5;
proxy_this.b = 7;
return proxy_this;
}
get scp_function() {
var proxy = this._scp_function()
for (var [key, value] of Object.entries(proxy)) {
this[key] = value;
}
this.random_string = "Hello, World!";
}
}
var new_SCP = new SCP_Object();
new_SCP.scp_function;
console.log(new_SCP);
If you'd like to set all those object properties without having to use your proxy functions at all, you can do so within the class itself with ease, whether using a function-style class or a newer ES6-style class:
function SCP_Object_1() {
this.a = 5;
this.b = 7;
this.random_string = "Hello, World!";
}
class SCP_Object_2 {
constructor() {
this.a = 5;
this.b = 7;
this.random_string = "Hello, World!";
}
}
var new_SCP_1 = new SCP_Object_1();
var new_SCP_2 = new SCP_Object_1();
console.log(new_SCP_1, new_SCP_2);

Related

How to access prototype property from within javascript class?

I am knew to javascript, please excuse my rather basic question.
How can I use a property from within my class, as in the sample code below?
function MyClass() {
// nothing special
}
MyClass.prototype.myProperty = {
key1: 'some value 1',
key2: 'some value 2',
};
My Class.prototype.myFunction = function myFunction() {
// I need to retrieve the first value of myProperty
const x = myProperty[Object.keys(myProperty)[0]] + 10; // won't work
return x;
};
module.exports = MyClass;
Using this.myProperty throws the error Cannot convert undefined or null to object
Use this.:
MyClass.prototype.myFunction = function myFunction() {
const x = this.myProperty[Object.keys(this.myProperty)[0]] + 10;
// -------^^^^^-----------------------^^^^^
return x;
};
That will get the property from the object. If the object doesn't have its own copy of the property, it will get it from the object's prototype.
Or if you want to get it from the prototype every time, be explicit:
MyClass.prototype.myFunction = function myFunction() {
const p = MyClass.prototype.myProperty;
const x = p[Object.keys(p)[0]] + 10;
return x;
};
Side note: const is a new thing, as of ES2015. If you're using ES2015 (and it looks like you're using NodeJS, which means you can if you're using v6 or later), you can write your class more simply using class notation:
class MyClass {
constructor() {
// nothing special
}
myFunction() {
const x = this.myProperty[Object.keys(this.myProperty)[0]] + 10;
return x;
}
}
MyClass.prototype.myProperty = {
key1: 'some value 1',
key2: 'some value 2',
};
module.exports = MyClass;
Note that if you want myProperty to be on the prototype, you do still need to assign it the "clunky" way. But you may want to create that property in the constructor instead.
Side note 2: Unless you change myProperty later, I strongly recommend using this.myProperty.key1 or this.myProperty.key2 and not using this.myProperty[Object.keys(this.myProperty)[0]], which is hard to read, chaotic (undefined behavior, the order of the keys returned by Object.keys is not specified, not even in ES2015), and extra work.

Define function for property of javascript class

I have this Javascript class and want to add some kind of function (like prototype)
to properties of this class.
function theUploader(virtualField)
{
var self = this;
//self.v = virtualField;
self.v = (function(){return self.v; this.clear = function(){self.v = '';}})()
self.v.prototype = function clear() {
self.v = '';
}
}
i tried those lines.
i couldn`t find out the right way to define such a thing.i want to call it like this
var temp = new theUploader('smart');
temp.v.clear();
someone guid me with jsaon.but still working on it
The problem(s) with this line:
self.v = (function(){return self.v; this.clear = function(){self.v = '';}})()
...would be more obvious if you split it out over several lines:
self.v = (function(){
return self.v;
this.clear = function(){
self.v = '';
}
})()
It's an immediately invoked function expression which returns on its first line, so it never gets to the this.clear = ... line. The value returned, self.v, will be undefined at that point, which means the self.v property you assign that value to will also be undefined, which means then on this line:
self.v.prototype = function clear() {
...you'll get an error TypeError: Cannot set property 'prototype' of undefined.
It's a bit hard to tell exactly what you're trying to do given the confusion in your theUploader() function, but given that you said you want to be able to do this:
var temp = new theUploader('smart');
temp.v.clear();
Then you need to create a .v property that is itself an object that has a .clear() method, so:
function theUploader(virtualField)
{
var self = this;
self.v = {}; // create a v property that is an object
self.v.clear = function(){self.v = '';}; // add a method to v
}
...would do it. Or you could define the clear function directly in the object literal:
self.v = {
clear : function(){self.v = '';}
};
(Either way it doesn't really make sense to me that calling self.v.clear() would actually overwrite the .v property with an empty string, but if that's what you want this is how you could do it.)
self.v.prototype = function clear() {
self.v = '';
}
Should be
self.v.clear = function() {
self.v = '';
}

variable in my javascript class is undefined when using an instance of that class

I have declared this javascript class:
var TablixColumns = function(){
this.g = 'wtf';
this.tablixColumns = []; //[];
return {
addTablixColumn: function(tablixColumn){
alert(this.g);
//this.tablixColumns.push(tablixColumn.getTablixColumn());
}
}
};
my problem is that when I try this: alert(this.g) the alert comes out undefined
of course my initial function definition read: this.tablixColumns.push(tablixColumn.getTablixColumn());
but then I get the error that reads something like "No Method push of undefined"
what's weird is I have this class declaration:
var TablixColumn = function(){
columnWidth = '<Width>3.135cm</Width>'; //default width value
return{
setColumnWidth: function(width){
this.columnWidth = '<Width>' + width + 'cm</Width>';
},
getTablixColumn: function(){
return '<TablixColumn>' + this.columnWidth + '</TablixColumn>';
}
}
};
and the TablixColumn class works fine,
and yes, I have declared this.g and this.tablixColumns without the 'this.' part, but it's just refusing to work!
I'm going to kill someone if this doesn't work tonight can someone help me please?
You need to set a reference to the current object (this) outside the nested function expression. Here's how your code should look:
var TablixColumns = function() {
...
var self = this;
return {
addTablixColumn: function(tablixColumn) {
alert(self.g);
}
};
};
You can even set a property to the returned object literal if you want:
// ...
return {
g: 'wtf',
addTablixColumn: function(tablixColumn) {
alert(this.g); // 'wtf'
}
};
// ...
Note that you shouldn't use TablixColumns as a constructor if you're returning from it like this. You're using two idioms here; prototypal inheritance and the module pattern. Are you going to instantiate the constructor with new? If so, then don't return the object literal. Rather, set the methods on the prototype of the function:
var TablixColumns = function() {
this.g = 'wtf';
this.tablixColumns = [];
};
TablixColumns.prototype.addTablixColumn = function addTablixColumn() { ... };
TablixColumns.prototype./* ... */
...
Otherwise, don't use this inside the constructor. Simply make the properties normal variables.
Okay guys so I figured out my problem:
all the references to variables of the current instance should not have been preceded by the this. keyword
so this is how my declaration looks now:
var TablixColumns = function(){
g = 'wtf';
tablixColumns = []; //[];
return {
addTablixColumn: function(tablixColumn){
alert(g);
tablixColumns.push(tablixColumn.getTablixColumn());
}
}
};
Thanks #Bergi for pointing this out

How can I count the instances of an object?

If i have a Javascript object defined as:
function MyObj(){};
MyObj.prototype.showAlert = function(){
alert("This is an alert");
return;
};
Now a user can call it as:
var a = new MyObj();
a.showAlert();
So far so good, and one can also in the same code run another instance of this:
var b = new MyObj();
b.showAlert();
Now I want to know, how can I hold the number of instances MyObj?
is there some built-in function?
One way i have in my mind is to increment a global variable when MyObj is initialized and that will be the only way to keep track of this counter, but is there anything better than this idea?
EDIT:
Have a look at this as suggestion here:
I mean how can I make it get back to 2 instead of 3
There is nothing built-in; however, you could have your constructor function keep a count of how many times it has been called. Unfortunately, the JavaScript language provides no way to tell when an object has gone out of scope or has been garbage collected, so your counter will only go up, never down.
For example:
function MyObj() {
MyObj.numInstances = (MyObj.numInstances || 0) + 1;
}
new MyObj();
new MyObj();
MyObj.numInstances; // => 2
Of course, if you want to prevent tampering of the count then you should hide the counter via a closure and provide an accessor function to read it.
[Edit]
Per your updated question - there is no way to keep track of when instances are no longer used or "deleted" (for example by assigning null to a variable) because JavaScript provides no finalizer methods for objects.
The best you could do is create a "dispose" method which objects will call when they are no longer active (e.g. by a reference counting scheme) but this requires cooperation of the programmer - the language provides no assistance:
function MyObj() {
MyObj.numInstances = (MyObj.numInstances || 0) + 1;
}
MyObj.prototype.dispose = function() {
return MyObj.numInstances -= 1;
};
MyObj.numInstances; // => 0
var a = new MyObj();
MyObj.numInstances; // => 1
var b = new MyObj();
MyObj.numInstances; // => 2
a.dispose(); // 1 OK: lower the count.
a = null;
MyObj.numInstances; // => 1
b = null; // ERR: didn't call "dispose"!
MyObj.numInstances; // => 1
Create a static property on the MyObj constructor called say count and increment it within the constructor itself.
function MyObj() {
MyObj.count++;
}
MyObj.count = 0;
var a = new MyObj;
var b = new MyObj;
alert(MyObj.count);
This is the way you would normally do it in say Java (using a static property).
var User = (function() {
var id = 0;
return function User(name) {
this.name = name;
this.id = ++id;
}
})();
User.prototype.getName = function() {
return this.name;
}
var a = new User('Ignacio');
var b = new User('foo bar');
a
User {name: "Ignacio", id: 1}
b
User {name: "foo bar", id: 2}
Using ES6 Classes MDN syntax - we can define a static method:
The static keyword defines a static method for a class. Static methods are called without instantiating their class and cannot be called through a class instance. Static methods are often used to create utility functions for an application.
class Item {
static currentId = 0;
_id = ++Item.currentId; // Set Instance's this._id to incremented class's ID
// PS: The above line is same as:
// constructor () { this._id = ++Item.currentId; }
get id() {
return this._id; // Getter for the instance's this._id
}
}
const A = new Item(); // Create instance (Item.currentId is now 1)
const B = new Item(); // Create instance (Item.currentId is now 2)
const C = new Item(); // Create instance (Item.currentId is now 3)
console.log(A.id, B.id, C.id); // 1 2 3
console.log(`Currently at: ${ Item.currentId }`); // Currently at: 3
PS: if you don't want to log-expose the internal currentId property, make it private:
static #currentId = 0;
_id = ++Item.#currentId;
Here's an example with constructor and without the getter:
class Item {
static id = 0;
constructor () {
this.id = ++Item.id;
}
getID() {
console.log(this.id);
}
}
const A = new Item(); // Create instance (Item.id is now 1)
const B = new Item(); // Create instance (Item.id is now 2)
const C = new Item(); // Create instance (Item.id is now 3)
A.getID(); B.getID(); C.getID(); // 1; 2; 3
console.log(`Currently at: ${ Item.id }`); // Currently at: 3
what about such method?
var Greeter = (function ()
{
var numInstances;
function Greeter(message)
{
numInstances = (numInstances || 0) + 1;
this.greeting = message;
}
Greeter.prototype.greet = function ()
{
return "Hello, " + this.greeting;
};
Greeter.prototype.getCounter = function ()
{
return numInstances;
};
return Greeter;
})();
var greeter = new Greeter("world");
greeter.greet();
greeter.getCounter();
var newgreeter = new Greeter("new world");
newgreeter.greet();
newgreeter.getCounter();
greeter.getCounter();
Keeping a global count variable and incrementing every time is an option. Another option is to call counter method after each instance creation by hand (the worst thing I could imagine). But there is another better solution.
Every time we create an instance, the constructor function is being called. The problem is the constructor function is being created for each instance, but we can have a count property inside __proto__ which can be the same for each instance.
function MyObj(){
MyObj.prototype.addCount();
};
MyObj.prototype.count = 0;
MyObj.prototype.addCount = function() {
this.count++;
};
var a = new MyObj();
var b = new MyObj();
This is our a and b variables after all:
Eventually, JS is going to have built-in proxy capability, which will have low-level access to all kinds of things which happen in the background, which will never be exposed to front-end developers (except through the proxy -- think magic-methods in languages like PHP).
At that time, writing a destructor method on your object, which decrements the counter might be entirely trivial, as long as support for destruction/garbage-collection as a trigger is 100% guaranteed across platforms.
The only way to currently, reliably do it might be something like creating an enclosed registry of all created instances, and then manually destructing them (otherwise, they will NEVER be garbage-collected).
var Obj = (function () {
var stack = [],
removeFromStack = function (obj) {
stack.forEach(function (o, i, arr) {
if (obj === o) { arr.splice(i, 1); }
makeObj.count -= 1;
});
};
function makeObj (name) {
this.sayName = function () { console.log("My name is " + this.name); }
this.name = name;
this.explode = function () { removeFromStack(this); };
stack.push(this);
makeObj.count += 1;
}
makeObj.checkInstances = function () { return stack.length; };
makeObj.count = 0;
return makeObj;
}());
// usage:
var a = new Obj("Dave"),
b = new Obj("Bob"),
c = new Obj("Doug");
Obj.count; // 3
// "Dave? Dave's not here, man..."
a.explode();
Obj.count; // 2
a = null; // not 100% necessary, if you're never going to call 'a', ever again
// but you MUST call explode if you ever want it to leave the page's memory
// the horrors of memory-management, all over again
Will this pattern do what you want it to do?
As long as:
you don't turn a into something else
you don't overwrite its explode method
you don't mess with Obj in any way
you don't expect any prototype method to have access to any of the internal variables
...then yes, this method will work just fine for having the counter work properly.
You could even write a general method called recycle, which calls the explode method of any object you pass it (as long as its constructor, or factory, supported such a thing).
function recycle (obj) {
var key;
obj.explode();
for (key in obj) { if (obj.hasOwnProperty(key)) { delete obj[key]; } }
if (obj.__proto__) { obj.__proto__ = null; }
}
Note - this won't actually get rid of the object.
You'll just have removed it from the closure, and removed all methods/properties it once had.
So now it's an empty husk, which you could reuse, expressly set to null after recycling its parts, or let it be collected and forget about it, knowing that you removed necessary references.
Was this useful?
Probably not.
The only time I really see this as being of use would be in a game where your character might only be allowed to fire 3 bullets at a time, and he can't shoot a 4th until the 1st one on screen hits someone or goes off the edge (this is how, say, Contra worked, in the day).
You could also just shift a "disappeared" bullet off the stack, and reuse that bullet for any player/enemy by resetting its trajectory, resetting appropriate flags, and pushing it back onto the stack.
But again, until proxies allow us to define "magic" constructor/destructor methods, which are honoured at a low-level, this is only useful if you're going to micromanage the creation and destruction of all of your own objects (really not a good idea).
My solution is creating an object store instance count and a function to increase them in prototype.
function Person() {
this.countInst();
}
Person.prototype = {
constructor: Person,
static: {
count: 0
},
countInst: function() {
this.static.count += 1;
}
};
var i;
for (i = 0; i < 10; i++) {
var p = new Person();
document.write('Instance count: ');
document.write(p.static.count);
document.write('<br />');
}
Here is my plunker: https://plnkr.co/edit/hPtIR2MQnV08L9o1oyY9?p=preview
class Patient{
constructor(name,age,id){
Object.assign(this,{name, age, id});
}
static patientList = []; // declare a static variable
static addPatient(obj){
this.patientList.push(...obj); // push to array
return this.patientList.length; // find the array length to get the number of objects
}
}
let p1 = new Patient('shreyas',20, 1);
let p2 = new Patient('jack',25, 2);
let p3 = new Patient('smith',22, 3);
let patientCount = Patient.addPatient([p1,p2,p3]); // call static method to update the count value with the newly created object
console.log(Patient.patientList);
console.log(patientCount);

javascript "polymorphic callable objects"

I saw this article on polymorphic callable objects and was trying to get it to work, however it seems that they are not really polymorphic, or at least they do not respect the prototype chain.
This code prints undefined, not "hello there".
Does this method not work with prototypes, or am I doing something wrong?
var callableType = function (constructor) {
return function () {
var callableInstance = function () {
return callableInstance.callOverload.apply(callableInstance, arguments);
};
constructor.apply(callableInstance, arguments);
return callableInstance;
};
};
var X = callableType(function() {
this.callOverload = function(){console.log('called!')};
});
X.prototype.hello = "hello there";
var x_i = new X();
console.log(x_i.hello);
You'd need to change this:
var X = callableType(function() {
this.callOverload = function(){console.log('called!')};
});
to this:
var X = new (callableType(function() {
this.callOverload = function(){console.log('called!')};
}));
Notice the new as well as the parentheses around the callableType invocation.
The parentheses allows callableType to be invoked and return the function, which is used as the constructor for new.
EDIT:
var X = callableType(function() {
this.callOverload = function() {
console.log('called!')
};
});
var someType = X(); // the returned constructor is referenced
var anotherType = X(); // the returned constructor is referenced
someType.prototype.hello = "hello there"; // modify the prototype of
anotherType.prototype.hello = "howdy"; // both constructors
var some_i = new someType(); // create a new "someType" object
console.log(some_i.hello, some_i);
var another_i = new anotherType(); // create a new "anotherType" object
console.log(another_i.hello, another_i);
someType(); // or just invoke the callOverload
anotherType();
I really don't know how/where/why you'd use this pattern, but I suppose there's some good reason.

Categories

Resources