Repeating Value and Replacing Value with JS - javascript

Newbie in JS here. I'm having trouble replacing and repeating the value from the function. Here's the code:
function Phone(ring) {
this.ring = ring;
}
function updateRing(newRing) {
this.newRing = ring;
}
var samsung = new Phone('Chim');
samsung.ring(2); // Needs to compute to "Chim, Chim"
var htc = new Phone('Dada');
htc.ring(3); // Needs to compute to "Dada, Dada, Dada"
htc.updateRing('Riri');
htc.ring(1); // Needs to compute to "Riri"
For the repeat value for the first function, I tried using this.repeat but it didn't work inside the Phone function.
For the updateRing function, I couldn't get the code to replace the this.ring.
I stripped down all the useless code I had written. Thanks in advance for any help.

You can repeat strings with string.repeat()
let a = "ring"
console.log(a.repeat(2))
But to get the comma separator to work cleanly you can make a disposable array and join() is with a comma.
let ringString = Array(3).fill("ring").join(", ")
console.log(ringString)
For the others, you probably want to use classes, which are pretty easy, but don't run on IE without a ployfill. Or prototypes, which can be a little confusing at first. Here's an example using prototypes to define methods on your Phone object:
function Phone(ring) {
// changed to ring_tone too prevent clash with this.ring method
this.ring_tone = ring;
}
// you need to define these on the prototype to you can use `this`
Phone.prototype.updateRing = function(newRing) {
// don't need to define a this.newRing, just update the ring
this.ring_tone = newRing;
}
Phone.prototype.ring = function(n) {
return new Array(n).fill(this.ring_tone).join(', ')
}
var samsung = new Phone('Chim');
console.log(samsung.ring(2)); // Needs to compute to "Chim, Chim"
var htc = new Phone('Dada');
console.log(htc.ring(3)); // Needs to compute to "Dada, Dada, Dada"
htc.updateRing('Riri');
console.log(htc.ring(1)); // Needs to compute to "Riri"

1) You're calling samsung.ring as a function, even though it's just an instance variable of Phone.
2) The reason why this.repeat didn't work is because repeat isn't a method of "this," which refers to Phone.
Try this instead:
var samsung = new Phone('Chim');
samsung.ring.repeat(2);
var htc = new Phone('Dada');
htc.ring.repeat(3);

Maybe try this:
class Phone {
constructor(sound) {
this.sound = sound;
}
ring(number) {
var i;
for (i = 0; i < number; i++) {
console.log(this.sound + ", ");
}
}
updateRing(newSound) {
this.sound = newSound;
}
}
var samsung = new Phone('Chim');
samsung.ring(2);
samsung.updateRing('Riri');
samsung.ring(1);
Codepen - https://codepen.io/anon/pen/MGRJOB?editors=0010

Related

create a new variable automaticaly

This is a general question. But an answer in JavaScript would suit me the best.
I'm searching for a way to create variables after a pattern automatically.
For example, I want to create a while-loop in which a variable gets declared. In set loop, I want to create the variable car1. However, in the next loop pass I want to do the same thing BUT call the Variable car2 this time.
I'll try to write it in pseudocode:
//this should happen in the first loop
while(true){
var car1 = 1 + 2;
console.log(car1)
}
//this should happen in the second loop
while(true){
var car2 = 1 + 2;
console.log(car)
}
//In both cases "3" should be the output. But different Variables
Contrary to this example. I want to do all this in a single while loop. And on every while loop, a new variable should be created. So car1,car2,car3,car4.
Thanks in advance!
Maybe you can use an array and add an item every loop iteration or a hash map with a naming convention you set for the keys
You can try to use globalThis or window.
function nameFunction(name, f) {
return {
[name](...args) {
return f(...args)
}
}[name]
}
// use globalThis
for (let i = 1; i <= 3; i++) {
const funcName = `car${i}`;
const func =
nameFunction(funcName, () => console.log(`this is car ${i}`));
globalThis[funcName] = func;
}
car1(); car2(); car3();
// use window
for (let i = 4; i <= 6; i++) {
const funcName = `car${i}`;
const func =
nameFunction(funcName, () => console.log(`this is car ${i}`));
window[funcName] = func;
}
car4(); car5(); car6();
I hope this link will help you with this problem.
JS Dynamic Variable
Here they have discussed 2 ways of solving the problem. (One with "eval" and the other with "windows" object.

I am trying to stop my function from displaying the same object twice when clicking a button

I have for quite some time now been trying to figure out how I can stop my code to print the same quote twice.
Also, when every single object in the array has been printed out, I'd like for it to reset somehow. So that you can browse through the quotes once you've gone through all of them.
This is the essential parts of my code:
document.getElementById('loadQuote').addEventListener("click", printQuote, false);
The printQuote function simply contains information that's accessing information from my array:
var randomObjectNumber = getRandomQuote();
var html = "<p class='quote'>"
+ quotes[randomObjectNumber].quote +
"</p>";
document.getElementById('quote-box').innerHTML = html;
One random object is displayed each time you click the eventListener:
function getRandomQuote () {
var randomObjectNumber = Math.floor(Math.random() * quotes.length );
return randomObjectNumber;
}
I have some ideas on how to do this and I have tried them but without success. I tried giving each object a boolean property but I can't really seem to assign each property a boolean value without messing the printQuote function up.
I also tried assigning the object displayed to a different array but the same problem occurred there.
I feel like there is some concepts around the eventListener that I don't fully understand, because every time I try to manipulate a displayed object I just end up changing every single object.
This is what a typical object in the array looks like by the way:
{quote : "Darkness is merely the absence of light"}
(I also have other properties assigned to the object but i feel like presenting them would be redundant)
If someone could explain, or give me a hint, on how to solve this problem I've been struggling with for some time.
Some hints would be greatly appreciated!
Have a nice day.
Sebastian.
EDIT: All code: https://jsfiddle.net/fusqb7hz/
Basically what you need:
Create a separate array that will store all quotes that you've already used.
Remove quote from initial array.
Check if you still have quotes in initial array, if not, get them back from backup array.
The problem is that you call addEventListener twice:
//Let's developers create multiple eventListeners without being redundant.
function onClicking (printFunction) {
document.getElementById('loadQuote').addEventListener("click", printFunction, false);
}
onClicking(printColor);
onClicking(printQuote);
by calling onClicking twice you make the click happen twice, so addEventListener is added twice, meaning one click counts as two.
Change the above code for this:
//Let's developers create multiple eventListeners without being redundant.
document.getElementById('loadQuote').addEventListener("click", function(){
printColor();
printQuote();
});
Here is the jsfiddle:
https://jsfiddle.net/fusqb7hz/3/
I think the easiest approach is to shuffle your quote array and then go through them one by one. This gives you the next "random" as yet unseen quote. The only part I'm not keen on is this shuffler (a derivation of Fisher Yates) modifies the original quote array. You might not care about that though.
// --------------------------------
// A bunch of quotes
// --------------------------------
var quotes = [];
quotes.push({quote : "Darkness is merely the absence of light"});
quotes.push({quote : "quote 2"});
quotes.push({quote : "quote 3"});
quotes.push({quote : "quote 4"});
quotes.push({quote : "quote 5"});
// --------------------------------
// --------------------------------
// Your favorite array shuffle utility
// --------------------------------
var shuffle = function(array) {
for (var i = array.length - 1; i > 0; i--) {
var j = Math.floor(Math.random() * (i + 1));
var temp = array[i];
array[i] = array[j];
array[j] = temp;
}
return array;
};
// --------------------------------
// --------------------------------
// construct a function to get a random unseen quote until
// all quotes have been seen. Then reset...
// --------------------------------
var getQuote = (function(quotes, shuffle){
var current = 0;
var get = function(){
if ( !quotes || !quotes.length ) { return ""; }
if ( current >= quotes.length ){ current = 0; }
if ( current === 0 ){
console.log("randomizing quotes...");
shuffle(quotes);
}
return quotes[current++].quote;
};
return get;
})(quotes, shuffle);
// --------------------------------
var printQuote = function(){
document.getElementById('quote').innerText = getQuote();
};
document.getElementById('loadQuote').addEventListener("click", printQuote, false);
<div id="quote"></div>
<button id="loadQuote">get quote</button>

JavaScript: Cannot set property of undefined

I'm pretty new to JS and I'm trying to wrap my head around the object topic in JS.
What I'm trying to do is to set a property of an object prototype to an uninitialized array, so that I can later add multiple objects to that array (for instances of the prototype object)
My code looks like this so far:
function cocktail(){
this.prototype.ingredients = [];
this.printIngredients = function() {
var i;
for (i = 0; i<this.ingredients.length; ++i) {
console.log(this.ingredients.fluid);
console.log(this.ingredients.amount);
}
}
}
var Mojito = new cocktail();
Mojito.ingredients.push({"fluid":"White Rum", "amount":0.05});
Mojito.printIngredients();
That throws:
TypeError: Cannot set property 'ingredients' of undefined
If I change my code into :
this.ingredients = [];
it works but the printIngredients() method prints undefined twice. When I do:
var array = [];
array.push({"a":1, "b":2});
console.log(array[0].a, array[0].b)
everything works as I would expect it to. Can someone clarify what I'm doing wrong and where my thoughts got mixed up?
Change your code to
function cocktail(){
this.ingredients = []; //this doesn't have prototype property
this.printIngredients = function() {
var i;
for (i = 0; i<this.ingredients.length; ++i) {
console.log(this.ingredients[i].fluid);//use the counter variable to get the fluid value at current counter value
console.log(this.ingredients[i].amount);//use the counter variable to get the amount value at current counter value
}
}
}
var Mojito = new cocktail();
console.log(Mojito.ingredients)
Mojito.ingredients.push({"fluid":"White Rum", "amount":0.05});
Mojito.printIngredients();
Alternatively, if you are familiar with class-based languages, you could use modern JavaScript to avoid some of the confusion.
class Cocktail {
constructor() {
this.ingredients = []
}
printIngredients() {
// let is like var, but scoped to blocks instead of functions
// for...of iterates on values instead of keys/indices
for (let ingredient of this.ingredients) {
console.log(ingredient.fluid)
}
}
}
This kind of JavaScript is available from:
Chrome 49
Edge 13
Firefox 44
Node.js 6
Documentation:
Classes
let
for...of
well, first you want to remove printIngredients method out of the constructor function, it will improve performance when it comes to a larger project since you don't have to create different copies every time you instantiate the constructor function, secondly, it is a convention to capitalize the first letter of your constructor. Last but not least, use let and const as they limit the scope to block rather than var that's function scope.
function Cocktail(){
this.ingredients = [];
}
Cocktail.prototype.printIngredients = function() {
// for in ... iterates on keys rather than values
for (let i in this.ingredients) {
console.log(this.ingredients[i].fluid);//use the counter variable to get the fluid value at current counter value
console.log(this.ingredients[i].amount);//use the counter variable to get the amount value at current counter value
}
}
const Mojito = new Cocktail();
console.log(Mojito.ingredients)
Mojito.ingredients.push({"fluid":"White Rum", "amount":0.05});
Mojito.printIngredients();

Javascript Invalid left-hand side in assignment

In an attempt to add queue type functionality to nodejs's Buffer class, I have constructed the following function:
Buffer.prototype.popleft = function(n) {
tRet = this.slice(0,n);
this = this.slice(n,this.length-1); // error here
return tRet;
};
however, this code yields the following error:
"ReferenceError: Invalid left-hand side in assignment"
I know that the issue is with the assignment of 'this' within the function, what I dont know is better way of accomplishing this same type of logic.
EDIT:
Ended up writing an object around the Buffer as shown below:
sPort.vBuffer = {}
sPort.vBuffer.buff = new Buffer(0);
sPort.vBuffer.off = 0;
sPort.vBuffer.expect = -1;
sPort.vBuffer.ReadChr = function() {
this.off ++;
return this.buff[this.off - 1];
};
sPort.vBuffer.ReadUInt32LE = function() {
this.off += 4;
return this.buff.readUInt32LE(this.off - 4);
}
sPort.vBuffer.ReadInt32LE = function() {
this.off += 4;
return this.buff.readInt32LE(this.off - 4);
}
sPort.vBuffer.Write = function(aData) {
this.buff = Buffer.concat([this.buff.slice(this.off),aData])
this.off = 0;
};
You can't assign to this. You can assign to a copy of it, but in your case it looks like that won't do any good.
According to the Node documentation, Buffer instances cannot be resized. Now, whether that's because Node simply provides no APIs to do that, or because of some set of internal implementation assumptions/dependencies, I don't know. There sure doesn't look like any way to alter the length of a Buffer instance.
You could use .copy to shift the contents, and then fill the last position(s) with some dummy value (null or undefined I guess).

How to set a dynamically generated pseudoclass name in JavaScript to work with the instanceof operator?

I'd like to set the name of a JavaScript pseudoclass stored in an array with a specific name, for example, the non-array version works flawlessly:
var Working = new Array();
Working = new Function('arg', 'this.Arg = arg;');
Working.prototype.constructor = Working;
var instw = new Working('test');
document.write(instw.Arg);
document.write('<BR />');
document.write((instw instanceof Working).toString());
Output:
test
true
However this format does not function:
// desired name of pseudoclass
var oname = 'Obj';
var objs = new Array();
objs.push(new Function('arg', 'this.Arg = arg;'));
// set objs[0] name - DOESN'T WORK
objs[0].prototype.constructor = oname;
// create new instance of objs[0] - works
var inst = new objs[0]('test');
document.write(inst.Arg);
document.write('<BR />Redundant: ');
// check inst name - this one doesn't need to work
try { document.write((inst instanceof objs[0]).toString()); } catch (ex) { document.write('false'); }
document.write('<BR />Required: ');
// check inst name - this is the desired use of instanceof
try { document.write((inst instanceof Obj).toString()); } catch (ex) { document.write('false'); }
Output:
test
Redundant: true
Required: false
Link to JSFiddle.
You've got a couple of things going on here that are a little bit off-kilter in terms of JS fluency (that's okay, my C# is pretty hackneyed as soon as I leave the base language features of 4.0).
First, might I suggest avoiding document.write at all costs?
There are technical reasons for it, and browsers try hard to circumvent them these days, but it's still about as bad an idea as to put alert() everywhere (including iterations).
And we all know how annoying Windows system-message pop-ups can be.
If you're in Chrome, hit CTRL+Shift+J and you'll get a handy console, which you can console.log() results into (even objects/arrays/functions), which will return traversable nodes for data-set/DOM objects and strings for other types (like functions).
One of the best features of JS these days is the fact that your IDE is sitting in your browser.
Writing from scratch and saving .js files isn't particularly simple from the console, but testing/debugging couldn't be any easier.
Now, onto the real issues.
Look at what you're doing with example #1.
The rewriting of .prototype.constructor should be wholly unnecessary, unless there are some edge-case browsers/engines out there.
Inside of any function used as a constructor (ie: called with new), the function is basically creating a new object {}, assigning it to this, setting this.__proto__ = arguments.callee.prototype, and setting this.__proto__.constructor = arguments.callee, where arguments.callee === function.
var Working = function () {};
var working = new Working();
console.log(working instanceof Working); // [log:] true
Working isn't a string: you've make it a function.
Actually, in JS, it's also a property of window (in the browser, that is).
window.Working === Working; // true
window["Working"] === Working; // true
That last one is really the key to solving the dilemma in example #2.
Just before looking at #2, though, a caveat:
If you're doing heavy pseud-subclassing,
var Shape = function () {
this.get_area = function () { };
},
Square = function (w) {
this.w = w;
Shape.call(this);
};
If you want your instanceof to work with both Square and Shape, then you have to start playing with prototypes and/or constructors, depending on what, exactly, you'd like to inherit and how.
var Shape = function () {};
Shape.prototype.getArea = function () { return this.length * this.width; };
var Square = function (l) { this.length = l; this.width = l; };
Square.prototype = new Shape();
var Circle = function (r) { this.radius = r; };
Circle.prototype = new Shape();
Circle.prototype.getArea = function () { return 2 * Math.PI * this.radius; };
var circle = new Circle(4),
square = new Square(4);
circle instanceof Shape; // true
square instanceof Shape; // true
This is simply because we're setting the prototype object (reused by every single instance) to a brand-new instance of the parent-class. We could even share that single-instance among all child-classes.
var shape = new Shape();
Circle.prototype = shape;
Square.prototype = shape;
...just don't override .getArea, because prototypical-inheritance is like inheriting public-static methods.
shape, of course, has shape.__proto__.constructor === Shape, much as square.__proto__.constructor === Square. Doing an instanceof just recurses up through the __proto__ links, checking to see if the functions match the one given.
And if you're building functions in the fashion listed above (Circle.prototype = new Shape(); Circle.prototype.getArea = function () { /* overriding Shape().getArea() */};, then circle instanceof Circle && circle instanceof Shape will take care of itself.
Mix-in inheritance, or pseudo-constructors (which return objects which aren't this, etc) require constructor mangling, to get those checks to work.
...anyway... On to #2:
Knowing all of the above, this should be pretty quick to fix.
You're creating a string for the desired name of a function, rather than creating a function, itself, and there is no Obj variable defined, so you're getting a "Reference Error": instead, make your "desired-name" a property of an object.
var classes = {},
class_name = "Circle",
constructors = [];
classes[class_name] = function (r) { this.radius = r; };
constructors.push(classes.Circle);
var circle = new constructors[0](8);
circle instanceof classes.Circle;
Now everything is nicely defined, you're not overwriting anything you don't need to overwrite, you can still subclass and override members of the .prototype, and you can still do instanceof in a procedural way (assigning data.name as a property of an object, and setting its value to new Function(data.args, data.constructor), and using that object-property for lookups).
Hope any/all of this helps.

Categories