I have an object with methods in it. I want one of the methods inmy obj to be able to use data in other nodes of my object;
myObj = {
state : { a:1, b:1},
addStuff: (x) => {
return state.a + x
}
}
myObj.addStuff(3)
what are the most elegant ways to do so? One way I know is to use the object name inside of it; return myObj.state.a + x
Are there better ways to accomplish the same? I did try both self and this inside the method but neither worked.
If the fat arrow is not the requirement don't use it.
myObj = {
state : { a:1, b:1},
addStuff: function(x) {
return this.state.a + x
}
}
myObj.addStuff(3)
or
myObj = {
state : { a:1, b:1},
addStuff(x) {
return this.state.a + x
}
}
console.log(myObj.addStuff(3))
Related
This may be a stupid question, but is it possible to create a new this on a method call of a class?
E.g:
const foo = new Foo();
console.log(foo.a(1).b(2));
// for example, outputs 3 (1+2)
// the a method will create a new namespace and attach 1 to it, and b will use that new namespace
console.log(foo.b(2));
// this will result in an error, as there is no new namespace from the a method anymore, so b cannot add to anything?
Maybe this is too hard to understand, sorry.
class Foo {
a(number) {
this.a = number;
return this;
}
b(number) {
return this.a + number;
}
}
This would be the code where it uses the same this variable - this doesn't fit what I wanted but is what I currently have.
// pseudo
class Foo {
a(number) {
const uniqueVariable = number
return uniqueVariable
// it'll somehow pass the number from this method to the next method
}
// where it can be used with the second method's input
b(uniqueVariable, number) {
return uniqueVariable + number
}
}
foo.a(1).b(2) = 3
This example would obviously cause an error because the return value of a() a number, not something to use a method on again.
Please let me know if I need to explain further -- I'm having some struggle explaining it properly.
If the intention is that foo.a(1).b(2) changes foo, or if you don't mind changing foo, the other answers here work.
But if you only want foo.a(1).b(2) to return 3 without modifying foo, then you need to return a new Foo.
Now, if you really hell bent on having console.log() print 3 rather than something like Foo { value: 3 }, you can also customize inspect() (given that the question is tagged with node.js).
All together:
const util = require('util');
class Foo {
constructor(value) {
this.value = value || 0;
}
add(value) {
return new Foo(this.value + value);
}
a(value) {
return this.add(value);
}
b(value) {
return this.add(value);
}
[util.inspect.custom]() {
return this.value;
}
}
const foo = new Foo();
console.log(foo);
console.log(foo.a(2).b(1));
console.log(foo);
Output:
0
3
0
On my solution, I decided to create two variables to hold the values of each method. (https://jsbin.com/wozuyefebu/edit?js,console)
The a() method will return a number if the isSingle parameter is set to true. If not, it will return the this object, allowing you to chain the b() method. This is might be a hack but I believe it solves your problem.
I write about Javascript and web development on my blog :) https://changani.me/blog
class Foo {
constructor() {
this.aValue = 0;
this.bValue = 0;
}
/**
* #param {Number} value
* #param {Boolean} isSingle
* #returns {Object/Number}
*/
a(value = 0, isSingle = false) {
this.aValue = value;
return isSingle ? this.aValue : this;
}
/**
* #param {Number} value
* #returns {Number}
*/
b(value = 0) {
this.bValue = this.aValue + value;
return this.bValue;
}
}
const x = new Foo();
console.log("Should return 3: ", x.a(2).b(1));
console.log("Should return an 2: ", x.a(2, true));
console.log("Should return an instance of the object: ", x.a(2));
console.log("Should return 1: ", x.b(1));
console.log("Should return 0: ", x.a().b());
(https://jsbin.com/wozuyefebu/edit?js,console)
If you want to be able to invoke methods on return value of methods, then, you should return this from those methods. However, you will need an additional method, say value() to actuall get the result of sum.
A possible way is show below.
class Foo {
_a = 0;
_b = 0;
a(number) {
this._a = number;
return this;
}
b(number) {
this._b = number;
return this;
}
value() {
return this._a + this._b;
}
}
const foo = new Foo();
console.log(foo.a(1).b(2).value());
console.log(foo.b(5).value());
I have a multidimensional object and using Vue, I am trying to make the inner object reactive.
My object looks like this:
data() {
return {
myObject: {}
}
}
And the filled data looks like this:
myObject: {
1: { // (client)
0: "X", // (index) : (value)
1: "Y"
},
2: {
0: "A",
2: "B"
}
}
If I try using:
let value = "X";
let client = 1;
let index = 1;
let obj = {};
obj[client][index] = value;
this.myObject = Object.assign({}, this.myObject, obj);
It throws an error:
TypeError: Cannot set property '0' of undefined
And if I try below, it overwrites the initial values as it is initially setting the object to {}
let obj = {};
obj[index] = value;
let parentObj = {};
parentObj[client] = obj;
this.myObject = Object.assign({}, this.myObject, parentObj);
What is the proper way of adding the values to the multidimensional object?
In javascript, dim2Thing[1][1] = ... expressions require dim2Thing[1] to exist. This is why you get the error you mentioned. So you can do two expressions, which should work fine:
dim2Thing[1] = dim2Thing[1] || {}
dim2Thing[1][1] = otherThing
For the last block, you mention that it "overwrites the initial values"
I think what's actually happening here is just that Object.assign is not recursive. It only merges top-level keys. So if parentObj has a key that over-laps with this.myObj, then sub-keys will be lost.
Object.assign({ a: { b: 2} }, { a: { c: 3 } }) // returns { a: { c: 3 } }
This is what I interpret your code as trying to do - though I am unfamiliar with vue.js at this time, so I cannot assure it will have the desired result to your webpage:
let value = "X";
let client = 1;
let index = 1;
const newObj = Object.assign({}, this.myObject);
// if you have lodash _.set is handy
newObj[client] = newObj[client] || {}; // whatever was there, or a new object
newObj[client][index] = value
this.myObject = newObj
Just use an array, thats reactive by design.
If you need to get elements from the array in your template or anywhere just add a find method
// temp
late
<div v-for="(value, idx) in myArray">{{find(obj => obj.id === idx)}}</div>
methods: {
find (searchFunction) {
return this.myArray.find(searchFunction)
}
}
This code is based on Coroutines guide example: Fan-out
val inputProducer = produce<String>(CommonPool) {
(0..inputArray.size).forEach {
send(inputArray[it])
}
}
val resultChannel = Channel<Result>(10)
repeat(threadCount) {
launch(CommonPool) {
inputProducer.consumeEach {
resultChannel.send(getResultFromData(it))
}
}
}
What is the right way to create a Sequence<Result> that will provide results?
You can get the channel .iterator() from the ReceiveChannel and then wrap that channel iterator into a Sequence<T>, implementing its normal Iterator<T> that blocks waiting for the result on each request:
fun <T> ReceiveChannel<T>.asSequence(context: CoroutineContext) =
Sequence {
val iterator = iterator()
object : AbstractIterator<T>() {
override fun computeNext() = runBlocking(context) {
if (!iterator.hasNext())
done() else
setNext(iterator.next())
}
}
}
val resultSequence = resultChannel.asSequence(CommonPool)
I had the same problem, and in the end I came up with this rather unusual/convoluted solution:
fun Channel<T>.asSequence() : Sequence<T> {
val itr = this.iterator()
return sequence<Int> {
while ( runBlocking {itr.hasNext()} ) yield( runBlocking<T> { itr.next() } )
}
}
I do not think it is particular efficient (go with the one provided by #hotkey), but it has a certain appeal to me at least.
I'm working with angular 4 and RxJS 5, I have an object with the following structure (with nested subjects, in this example only 2 levels):
objs = BehaviorSubject<MyObj[]>;
MyObj = {
prop1: BehaviorSubject<string> = "prop1";
prop2: BehaviorSubject<string> = "prop2";
prop1.subscribe(newValue => prop2 = prop1);
}
So if I try to output the value of objs I got something like the following:
console.log(objs.value) =>
[
{
prop1: BehaviorSubject<string>;
prop2: BehaviorSubject<string>;
},
{
...
}]
so the result doesn't include the values of prop1 and prop2 but I still have BehaviorSubject at the second level.
Is there a way to get the nested objs value like the following?:
objs = [{
prop1: "prop1";
prop2: "prop2"
}, {...}]
I'm wondering if there's a sort of the knockout ko.toJSON (http://knockoutjs.com/documentation/plugins-mapping.html)
Do you think it is generally a bad practice to have nested BehaviorSubjects or people do it everyday :)?
No, there is nothing builtin that does that. You could certainly roll your own method. This might be something you can start with:
function isPrimitive(obj: any) {
return obj !== Object(obj);
}
function desubjectify(obj: any) {
if(isPrimitive(obj)) {
return obj;
}
if(obj instanceof BehaviorSubject) {
return desubjectify(obj.value);
}
let transformed: any = {};
for(let key of Object.keys(obj).filter(key => !key.startsWith('_'))) {
let value = obj[key];
if(value instanceof BehaviorSubject) {
transformed[key] = desubjectify(value.value);
} else {
transformed[key] = desubjectify(value);
}
}
return transformed;
}
Nested behavior subjects seems fishy to me but I wouldn't rule it out immediately with out knowing more details. However, I would recommend you find a good tutorial on ngrx/store and read it. Anytime people start to work a lot with behavior subjects I would recommend this.
Is it possible to mock getter and setter of the property by Mockito? Something like this:
#Test
fun three() {
val m = mock<Ddd>() {
// on { getQq() }.doReturn("mocked!")
}
assertEquals("mocked!", m.qq)
}
open class Ddd {
var qq : String = "start"
set(value) {
field = value + " by setter"
}
get() {
return field + " by getter"
}
}
To mock getter just write:
val m = mock<Ddd>()
`when`(m.qq).thenReturn("42")
also i suggest to use mockito-kotlin, to use useful extensions and functions like whenever:
val m = mock<Ddd>()
whenever(m.qq).thenReturn("42")
Complementing IRus' answer, you could also use the following syntax:
val mockedObj = mock<SomeClass> {
on { funA() } doReturn "valA"
on { funB() } doReturn "valB"
}
or
val mockedObj = mock<SomeClass> {
on(it.funA()).thenReturn("valA")
on(it.funB()).thenReturn("valB")
}