This question already has answers here:
Is there a way to provide named parameters in a function call in JavaScript?
(12 answers)
Closed 2 years ago.
Say I have a class
class Something {
constructor(a, b) {
this.a = a;
this.b = b;
}
}
How can I instantiate an object so that I only assign a value to b without assigning a value to a ?
e.g. something along the lines of:
let someObject = new Something(b : 10);
with the expected output:
log(someObject.a) // undefined
log(someObject.b) // 10
I want to avoid let someObject = new Something(undefined, 10); if I can for code readability reasons.
I'm kinda new to js, and I'm not really sure if this is even possible, but any help or guidance would be greatly appreciated!
You can do like:
class Something{
// private properties don't even work in Firefox and the syntax is just more typing than constructors
constructor(b, a){
this.a = a;
this.b = b;
}
}
const something = new Something(10);
console.log(something);
But I would do:
function Something(b, a){
let see = 'Wow these private varibles are really easy to use in costructors! Classes are lame!';
this.a = a; this.b = b;
}
const something = new Something(10);
console.log(something);
After reading your comment:
function Something(){
this.objects = [].slice.call(arguments);
this.getObjIndex = obj=>{
return this.objects.indexOf(obj);
}
this.getObjByIndex = index=>{
return this.objects[index];
}
}
const objTest1 = {test:1}, objTest2 = {test:2}, objTest3 = {really:'cool', why:['a', 2, 'z']};
const something = new Something(objTest1, objTest3);
console.log(something.objects);
console.log(something.getObjIndex(objTest3));
console.log(something.getObjByIndex(0));
#VLAZ had so many comments (which I have no problem with, by the way) that I have to show about private variables:
function PrivateTest(){
let test = 'cool';
this.getTest = ()=>{
return test;
}
this.setTest = mixed=>{
test = mixed;
return this;
}
}
const pt = new PrivateTest;
console.log(pt.getTest());
console.log(pt.setTest('Look, VLAZ, it works!').getTest());
Related
Let's say I have a class like following:
class SomeClass {
constructor(a, b) {
this.a = a;
this.b = b;
}
}
How can I test through Jest that constructor was initialized the right way? Say... this.a = a and this.b = b and not vice versa?
I know that I can execute toBeCalledWith but that won't let me check the constructor's logic. I was also thinking about making mockImplementation but in this case it seems pointless as I will rewrite the logic, or I may not be aware of all the nuances of creating mocks
Just create an instance of the object and check it directly. Since it sets them on this, they are essentially public values:
it('works', () => {
const obj = new SomeClass(1, 2);
expect(obj.a).toBe(1);
expect(obj.b).toBe(2);
});
You can simply check the instance properties after initializing the class. Basicly the same as you can test the side effects of any function.
const a = Symbol();
const b = Symbol();
const classInstance = new SomeClass(a, b);
expect(classInstance.a).toBe(a);
expect(classInstance.b).toBe(b);
if you know where the class is coming from you can do something like this:
jest.mock('path/to/module');
...
it('should work', () => {
const a = Symbol();
const b = Symbol();
expect(SomeClass).toBeCalledWith(a, b);
});
This question already has answers here:
Private properties in JavaScript ES6 classes
(41 answers)
Closed 5 years ago.
I want to build a class using javascript like in c, the main problem is private attribute.
var tree = {
private_var: 5,
getPrivate:function(){
return this.private_var;
}
};
console.log(tree.private_var);//5 this line want to return unaccessible
console.log(tree.getPrivate());//5
so I want to detect the access from tree.private_var and return unaccessible, and this.private_var return 5.
My question is: Is there any way to set private attribute in javascript?
EDIT: I saw this way
class Countdown {
constructor(counter, action) {
this._counter = counter;
this._action = action;
}
dec() {
if (this._counter < 1) return;
this._counter--;
if (this._counter === 0) {
this._action();
}
}
}
CountDown a;
a._counter is not accessible?
but
Define tree as a function instead of JavaScript object, define private variable in the function by var keyword, define public getting function by this. keyword and create a new instance by using the function
var Tree = function(){
var private_var = 5;
this.getPrivate = function(){
return private_var;
}
}
var test = new Tree();
test.private_var; //return undefined
test.getPrivate(); //return 5
In ES6, you can do this but it is not supported by IE so I wouldn't recommend
class Tree{
constructor(){
var private_var =5;
this.getPrivate = function(){ return private_var }
}
}
var test = new Tree();
test.private_var; //return undefined
test.getPrivate(); //return 5
What is the proper way to create singleton in JS since ES2015?
I know of many ways such as:
(() => {
let instance;
class Singleton{
constructor(){
instance = instance || this;
}
}
window.Singleton = Singleton; // or sth to export this class
})();
var a = new Singleton();
var b = new Singleton(); // a is the same as b
But it doesn't seem like a good way to use "new" operator with a Singleton class. So my question is whether there is a "proper" way to create a Singleton in ES6
This one seems to work for me:
let instance;
export default class AudioContext {
static getInstance() {
if (!instance) {
instance = {
context:new window.AudioContext() || new window.webkitAudioContext(),
contextCreatedAt: new Date()
}
}
return instance;
}
}
I have created 2 instances of AudioContext at different times. I then checked the time in contextCreatedAt (returns the same) and context === context on the 2 - however please elaborate if I am wrong here.
var a = (function () {
// can put private vars/methods here.
var a = 3;
var b = 5;
var sum = () => a+b;
return {// your singleton object
getSum: sum
// ...
};
}());
I am trying to pass to my class constructor an object with predefined properties.
like this
class Test {
constructor({
a = "test a",
b = "test b"
}) {
}
}
P.S. I know how to define properties of objects. I want to know how to predefine properties.
It seems you want to pass one object to the constructor and have its properties assigned to single keys of the class. You can use destructuring for that this way:
class MyClass {
constructor({a,b} = {a:1,b:2}) {
this.a = a;
this.b = b;
}
}
Be aware that this is not safe for partially filled objects:
var instance = new MyClass({a:3});
// instance.b == undefined
Handling this could be done like so:
class MyClass {
constructor({a=1,b=2} = {}) {
this.a = a;
this.b = b;
}
}
Which results in:
var instance = new MyClass({a:3});
// instance.a == 3
// instance.b == 2
The simple solution would be to pass the constructor and object during instantiation:
class Test {
constructor(obj){
this.a = obj.a;
this.b = obj.b;
}
};
const obj = {
a: 'value',
b: 'value'
};
const newtTest = new Test(obj);
Like I said in my comment, there's an example right at the top of the documentation.
class Test {
constructor(/* put arguments here if you want to pass any */){
//Pre-define a and b for any new instance of class Test
this.a = "test a";
this.b = "test b";
}
}
I have a method in a base class that I want to keep in a subclass, but just add to it. I've found lots of stuff on augmenting classes and objects with properties and methods, but I can't find, or don't understand, how to just augment the method. The worst case scenario is that I would have to paste the entire method of the parent class into the subclass, but that seems like duplicate code... please help
function someObject (){
this.someProperty = 1;
this.incrementProperty = function incrementProperty(){
this.propertyOfSomeObject += 1;
}
}
function newObject (){
someObject.call(this);
this.incrementProperty = function incrementProperty(){
//do everything the super class has for this property already
return this.someProperty;
}
}
var incrementer = new newObject;
alert (incrementer.incrementProperty()); //I want output to be 2
// parent object
function someObject () {
this.someProperty = 1;
}
// add incrementProperty to the prototype so you're not creating a new function
// every time you instantiate the object
someObject.prototype.incrementProperty = function() {
this.someProperty += 1;
return this.someProperty;
}
// child object
function newObject () {
// we could do useful work here
}
// setup new object as a child class of someObject
newObject.prototype = new someObject();
// this allows us to use "parent" to call someObject's functions
newObject.prototype.parent = someObject.prototype;
// make sure the constructor points to the right place (not someObject)
newObject.constructor = newObject;
newObject.prototype.incrementProperty = function() {
// do everything the super class has for this property already
this.parent.incrementProperty.call(this);
return this.someProperty;
}
var incrementer = new newObject();
alert (incrementer.incrementProperty()); // I want output to be 2
See: http://jsfiddle.net/J7RhA/
this should do, you have to use prototype to have a real concept of oo with javascript
function someObject (){
this.someProperty = 1;
this.propertyOfSomeObject = 0;
this.incrementProperty = function incrementProperty(){
this.propertyOfSomeObject += 1;
return this.propertyOfSomeObject;
}
}
function newObject (){
someObject.call(this);
this.incrementProperty = function incrementProperty(){
this.__super__.incrementProperty.apply(this);
return this.propertyOfSomeObject + 1;
}
}
newObject.prototype = new someObject()
newObject.prototype.__super__ = newObject.prototype
var incrementer = new newObject();
alert(incrementer.incrementProperty()); //I want output to be 2
experiment removing incrementProperty from newObject and it will return 1
I usually use the augment library to write classes in JavaScript. This is how I would rewrite your code using augment:
var Foo = Object.augment(function () {
this.constructor = function () {
this.someProperty = 1;
};
this.incrementProperty = function () {
this.someProperty++;
};
});
var Bar = Foo.augment(function (base) {
this.constructor = function () {
base.constructor.call(this);
};
this.incrementProperty = function () {
base.incrementProperty.call(this);
return this.someProperty;
};
});
As you can see since Bar extends Foo it gets Foo.prototype as a parameter (which we call base). This allows you to easily call the base class constructor and incrementProperty functions. It also shows that the constructor itself is just another method defined on the prototype.
var bar = new Bar;
alert(bar.incrementProperty());
The output will be 2 as expected. See the demo for yourself: http://jsfiddle.net/47gmQ/
From this answer:
Overriding functions
Sometimes children need to extend parent functions.
You want the 'child' (=RussionMini) to do something extra. When RussionMini can call the Hamster code to do something and then do something extra you don't need to copy and paste Hamster code to RussionMini.
In the following example we assume that a Hamster can run 3km an hour but a Russion mini can only run half as fast. We can hard code 3/2 in RussionMini but if this value were to change we have multiple places in code where it needs changing. Here is how we use Hamster.prototype to get the parent (Hamster) speed.
// from goog.inherits in closure library
var inherits = function(childCtor, parentCtor) {
function tempCtor() {};
tempCtor.prototype = parentCtor.prototype;
childCtor.prototype = new tempCtor();
childCtor.prototype.constructor = childCtor;
};
var Hamster = function(name){
if(name===undefined){
throw new Error("Name cannot be undefined");
}
this.name=name;
}
Hamster.prototype.getSpeed=function(){
return 3;
}
Hamster.prototype.run=function(){
//Russionmini does not need to implement this function as
//it will do exactly the same as it does for Hamster
//But Russionmini does need to implement getSpeed as it
//won't return the same as Hamster (see later in the code)
return "I am running at " +
this.getSpeed() + "km an hour.";
}
var RussionMini=function(name){
Hamster.apply(this,arguments);
}
//call this before setting RussionMini prototypes
inherits(RussionMini,Hamster);
RussionMini.prototype.getSpeed=function(){
return Hamster.prototype
.getSpeed.call(this)/2;
}
var betty=new RussionMini("Betty");
console.log(betty.run());//=I am running at 1.5km an hour.