Why object is not proxied like an argument in function - javascript

i have an interesting example of code that's not working like i'm expected.
I really dont understand why my obj wouldnt proxy.
I'm expect that obj ill proxy via link, but it's not. Can anyone explain how it's works and what I don't understand? Thank you!
let obj = {
foo: "123"
};
function test(fn, object) {
object = new Proxy(object, {
get(target, key) {
console.log('get');
return target[key];
},
set(target, key, value) {
console.log('set');
target[key] = value;
return true;
}
});
fn();
}
test(() => {
obj.foo = "helloworld";
console.log(obj.foo);
}, obj);
UPD: i want to assign object to proxy variable ONLY through arguments can i?

Either assign the proxy to obj
let obj = {
foo: "123"
};
function test(fn, object) {
obj = new Proxy(object, {
get(target, key) {
console.log('get');
return target[key];
},
set(target, key, value) {
console.log('set');
target[key] = value;
return true;
}
});
fn();
}
test(() => {
obj.foo = "helloworld";
console.log(obj.foo);
}, obj);
Or pass the proxy as an argument
let obj = {
foo: "123"
};
function test(fn, object) {
const o = new Proxy(object, {
get(target, key) {
console.log('get');
return target[key];
},
set(target, key, value) {
console.log('set');
target[key] = value;
return true;
}
});
fn(o);
}
test((o) => {
o.foo = "helloworld";
console.log(o.foo);
}, obj);

Related

Typescript errors on what should be a basic object

I have the following error in my typescript, and I have no idea how to get around it?
Parameter 'key' implicitly has an 'any' type.
Below is my code, I don't fully understand the problem, even if I type them any I get the error?
let store = {};
return {
getItem: (key) => {
return store[key] || null;
},
setItem: (key, value) => {
store[key] = value.toString();
},
removeItem: (key) => {
delete store[key];
},
clear: () => {
store = {};
},
};
};
The solution was typing the key at the point of the object creation
const fakeLocalStorage = () => {
let store: { [key: string]: string } = {};
return {
getItem: (key: string) => {
return store[key] || null;
},
setItem: (key: string, value: string) => {
store[key] = value.toString();
},
removeItem: (key: string) => {
delete store[key];
},
clear: () => {
store = {};
},
};
};

search array within a object in javascript / typescript

I want to find the first array in an object in Javascript. However my functions cause an error:
el is undefined
el contains the object that looks like this:
data = {
foo: {
bar: [{object a},
{object b},
{object c}
]
}
}
let el = data;
el = this.searchArray(el);
el.forEach(element => {
console.log(element);
let siblingData = this.injectFilterParameters(element);
});
//here is unimportant code
searchArray(obj) {
if (Array.isArray(obj)) {
return obj;
} else {
Object.keys(obj).forEach(key => {
if (Array.isArray(obj[key])) {
return obj[key];
} else {
return this.searchArray(obj[key]);
}
})
}
}
const data = {
foo: {
bar: [
{ object: 'a' },
{ object: 'b' },
{ object: 'c' }
]
}
}
console.log(findArray(data))
function findArray(data: unknown): unknown[] | undefined {
if (Array.isArray(data)) {
return data
}
if (typeof data !== 'object') {
return undefined
}
const object = data as Record<string, unknown>
for (const key of Object.keys(object)) {
const value = object[key]
const valueSearchResult = findArray(value)
if (valueSearchResult != undefined) {
return valueSearchResult
}
}
return undefined
}

Normalise Javascript object

I have a json object with objects inside of it
such as user: {"name": "tim"} and would like a way to turn that in "user.name": 'tim'
I've tried: Javascript Recursion normalize JSON data
Which does not return the result I want, also tried some packages, no luck
You can use a recursive approach to flatten nested objects, by concatenating their keys, as shown below:
const flattenObject = (obj) => {
const flatObject = {};
Object.keys(obj).forEach((key) => {
const value = obj[key];
if (typeof value === 'object') {
const flatNestedObject = flattenObject(value);
Object.keys(flatNestedObject).forEach((nestedKey) => {
flatObject[`${key}.${nestedKey}`] = flatNestedObject[nestedKey];
});
} else {
flatObject[key] = value;
}
});
return flatObject;
};
const obj = {
user: { name: 'tim' },
};
console.log(flattenObject(obj));
This solution works for any amount of levels.
If your environment does not support Object.keys, you can use for..in instead:
const flattenObject = (obj) => {
const flatObject = {};
for (const key in obj) {
if (!obj.hasOwnProperty(key)) continue;
const value = obj[key];
if (typeof value === 'object') {
const flatNestedObject = flattenObject(value);
for (const nestedKey in flatNestedObject) {
if (!flatNestedObject.hasOwnProperty(nestedKey)) continue;
flatObject[`${key}.${nestedKey}`] = flatNestedObject[nestedKey];
}
} else {
flatObject[key] = value;
}
}
return flatObject;
};
const obj = {
user: { name: 'tim' },
};
console.log(flattenObject(obj));
This can easily be done like so:
const myObject = {
user: {
firstname: "john",
lastname: "doe"
}
}
function normalize(suppliedObject = {}) {
const newObject = {};
for (const key of Object.keys(suppliedObject)) {
for (const subKey of Object.keys(suppliedObject[key])) {
newObject[`${key}.${subKey}`] = suppliedObject[key][subKey];
}
}
return newObject;
}
console.log(normalize(myObject));
Be aware that this only normalizes 1 level deep. You can extend the function to normalize all the way down to the last level.

proxy handler with deep nested objects

I want to make a proxy handler for any composite object. For example, an object like this (I want to handle function call):
let = obj {
a: {
b: {
c: callback => setTimeout(() => callback(null, 'hello'), 2000)
}
},
aa: {
bb: (callback, x, y) => setTimeout(() => callback(null, x + y), 40000)
}
};
I made a simple handler, but it doesn't work with nested properties:
var handler = {
get: function(target, name) {
return typeof target[name] == 'function' ? 'function call' : target[name];
}
}
I can a make handler to wrap each property in proxy. It works, but I think it is not the best way:
var handler = {
get: function(target, name) {
if (typeof target[name] == 'function') {
return 'function call';
}
return typeof target[name] == 'object' ? new Proxy(target[name], handler) : target[name];
}
}
Is there more efficient way to solve this problem?
var obj = {
a: {
b: {
c: callback => setTimeout(() => callback(null, 'hello'), 2000)
}
},
aa: {
bb: (callback, x, y) => setTimeout(() => callback(null, x + y), 40000)
}
};
var handler = {
get: function(target, name) {
if (typeof target[name] == 'function') {
return 'function call';
}
return typeof target[name] == 'object' ? new Proxy(target[name], handler) : target[name];
}
}
var p = new Proxy(obj, handler);
p.a.b.c

Proxy on a date object

Simple question I am trying the following in my console
let a = new Proxy(new Date(), {})
I am expecting to be able to call
a.getMonth();
but it does not work it throws:
Uncaught TypeError: this is not a Date object.
at Proxy.getMonth (<anonymous>)
at <anonymous>:1:3
Funny part is that in Chrome the autocomplete does suggest all the Date functions on a. What am I missing?
Edit in response for #Bergi
I realized that there is a bug in this code aside for my question but here is what I am trying to do:
class myService {
...
makeProxy(data) {
let that = this;
return new Proxy (data, {
cache: {},
original: {},
get: function(target, name) {
let res = Reflect.get(target, name);
if (!this.original[name]) {
this.original[name] = res;
}
if (res instanceof Object && !(res instanceof Function) && target.hasOwnProperty(name)) {
res = this.cache[name] || (this.cache[name] = that.makeProxy(res));
}
return res;
},
set: function(target, name, value) {
var res = Reflect.set(target, name, value);
that.isDirty = false;
for (var item of Object.keys(this.original))
if (this.original[item] !== target[item]) {
that.isDirty = true;
break;
}
return res;
}
});
}
getData() {
let request = {
...
}
return this._$http(request).then(res => makeProxy(res.data);
}
Now getData() returns some dates
My original answer was all wrong. But the following handler should work
const handler = {
get: function(target, name) {
return name in target ?
target[name].bind(target) : undefined
}
};
const p = new Proxy(new Date(), handler);
console.log(p.getMonth());

Categories