JavaScript - Object property as a function result like Array.length - javascript

I want to create property work as a result of function, like Array.length or VideoElement.currentTime.
But I don't want to use it like function call when the object is used.
For example:
var obj = {
now : /* ??? */
}
console.log(obj.now)
Result : 2020-04-07 10:03:21
// 1 hours later
console.log(obj.now)
Result : 2020-04-07 11:03:21
// I don't want to implement like below:
console.log( obj.now() )
How can I implement it?

Make it into a getter instead of a normal function:
const obj = {
get now() {
return new Date().toString();
}
};
console.log(obj.now);
setTimeout(() => {
console.log(obj.now);
}, 1000);

You can do this using object getters:
const obj = {
get now() {
return Date.now()
}
}
console.log(obj.now)
// logs: 15870XXXXXXXX

Store the function result and then use:
Object.defineProperty()
I would need a little more on what you're trying to do.
mozilla doc I referenced

Related

updating object does not show the new property

the code in the example works fine but in my codes it doesn't
I`m trying to update object with a new property
const overrides = {paths:{"/":{}}}
const aItems = [{endpoint:"/test"}]
const mockOverrides = JSON.parse(JSON.stringify(overrides));
aItems.forEach(({endpoint}) => {
if (!mockOverrides.paths[endpoint]) {
mockOverrides.paths[endpoint] = {};
}
console.log(mockOverrides); // result {paths:{"/":{}}} expected {paths:{"/":{}, "/test":{}}}
console.log(mockOverrides.paths[endpoint]) // result is {} twice
})
as you can see the property is not displayed in the output
but is somehow exist why this happening?
After adding a ) to the end of the foreach method, it appears to be working fine:
const overrides = {paths:{"/":{}}}
const aItems = [{endpoint:"/test"}]
const mockOverrides = JSON.parse(JSON.stringify(overrides));
aItems.forEach(({endpoint}) => {
if (!mockOverrides.paths[endpoint]) {
mockOverrides.paths[endpoint] = {};
}
console.log(mockOverrides); // result {paths:{"/":{}}} expected {paths:{"/":{}, "/test":{}}}
console.log(mockOverrides.paths[endpoint]) // result is {} twice
});
Yeah. I wrote that but it was deleted. You were missing the ). Other than that the code is fine.
Maybe because the new property was set to __proto__ of mockOverrides.paths
why console.log doesn't show values of properties added by PROTOTYPES in javascript when whole object is printed?
You can reproduce it by run below code on chrome console (also get from the quote above)
var Person=function (name) {
this.Fname=name;
this.health=100;
};
var Mateen=new Person("Mateen");
console.log(Mateen);
// result: { Fname: 'Mateen', health: 100 }
Person.prototype.level=1;
console.log(Mateen);
// result: { Fname: 'Mateen', health: 100 }
console.log(Mateen.level);
// result: 1

how to get return value from a method or constructor in TS/JS?

I want to create something like momentJS where it can return a value with this moment() method and it also can have chaining function like moment().add(1, 'd').timezone('Asia/Singapore').format('LLL') or just . moment().timezone('Asia/Singapore')
I tried to create something like above in Javascript / Typescript using classes.
So, How can I get return value and chaining function within one method?.
Suppose I have method called molent()
class Time {
constructor () {
this.time = '';
}
format (format) {
if (format) {
let formatResult = // some method
this.time = formatResult;
}
return this;
}
add (n, d) {
if (n && d) {
let addResult = // some method
this.time = addResult;
}
return this;
}
timezone (tz) {
if (tz) {
let tzResult = // some method
this.time = tzResult;
}
return this;
}
}
function molent () {
let t = new Time()
return t
}
molent().format();
//it returns { time: '' }
//I want it returning a value
molent();
//it returns { time, format, add, timezone }
//I want it returning a value
What I want is the molent() will return a value ex. datetime now like moment instead of object. and I also want the chaining function return result value not an object.
Add toString() method to your Time class. When you use object as string it retuns that toString() returned value.
toString() {
return this.time;
}

Javascript returning value if no method chaining is available

I'm just getting started with the method chaining concept in javascript. I'm aware of returning this to chain methods but I'm using revealing module pattern here.
Code:
var currency = (function(){
var rates = {
INR: 64.10
};
function convert(value){
return value * rates["INR"];
//"return this"? and also get the return value (if no chained mathods) ?
}
function format(){
return this.replace(/(\d)(?=(\d{3})+(?!\d))/g, "$1,");
}
return {
convert: convert,
format: format
}
})();
I'll call the function in two different ways.
currency.convert(100); //6410; right now it returns rate and this is
expected
currency.convert(1000).format(); //64,100; this is expected
But the problem is if I return this; from the convert function how would #1 be possible? If I don't return this from the convert function method chaining won't be possible.
Q: convert() function in this pattern should be able to perform conversion and return the value if no chaining is requested and should be able to perform chaining?
Please ignore if the format function wrong.
As mentioned in the comments, the pattern you showed in the OP is not suited for chaining. But what you are trying to achieve is absolutely fine. Look through the embedded script to see how this can be done
let CurrencyConverter = (function() {
const rates = {
INR: 64.10
}
// CurrencyConverter class
function CurrencyConverter() {
// instantiate with new
// 'this' inside this function is the new instance
// of CurrencyConverter
this.value = 0;
}
// Add convert method
// this method just convert the value and store it
CurrencyConverter.prototype.convert = function convert(value) {
this.value = value * rates["INR"];
return this;
}
// Add format method
// this method formats the rate and
// return the formatted output
CurrencyConverter.prototype.format = function format() {
return (this.value + "").replace(/(\d)(?=(\d{3})+(?!\d))/g, "$1,");
}
// add as many more methods as you want
// ...
// finally return the 'class'
return CurrencyConverter;
})()
// instantiate new converter
let converter = new CurrencyConverter();
// convert
console.log(converter.convert(75).format())
NOTE: The snippet above is not 100% perfect but it is there just to give an idea of how this can be achieved in javascript.
UPDATE - 1
Based on the comment, here is an alternate approach:
let converter = (function() {
// constant rates
const rates = {
INR: 64.10,
GBP: 1.29
}
// converter function
return function convert(value, currency) {
let _val = (value * rates[currency || "INR"]).toFixed(2)
let ret = {}
// value getter
Object.defineProperty(ret, 'value', {
get: () => _val
});
// value formatter
Object.defineProperty(ret, 'formatted', {
get: () => (_val + "").replace(/(\d)(?=(\d{3})+(?!\d))/g, "$1,")
});
return ret;
}
})();
// use it like
console.log(converter(125).value)
console.log(converter(120, "GBP").formatted)

Substitute variables in strings like console.log

I want to substitute variables in a string like console.log does.
What I want to achieve is something like this:
let str = 'My %s is %s.';
replaceStr(string, /* args */) {
// I need help with defining this function
};
let newStr = replaceStr(str, 'name', 'Jackie');
console.log(newStr);
// output => My name is Jackie.
/*
This is similar to how console.log does:
// console.log('I\'m %s.', 'Jack');
// => I'm Jack.
*/
I am not able to figure out how to do that. Any help will be much appreciated.
Thank you.
You could prototype it to the String object. Something like this:
String.prototype.sprintf = function() {
var counter = 0;
var args = arguments;
return this.replace(/%s/g, function() {
return args[counter++];
});
};
let str = 'My %s is %s.';
str = str.sprintf('name', 'Alex');
console.log(str); // 'My name is Alex'
You can use spread operator (ES6):
function replaceStr(string, ...placeholders) {
while (placeholders.length > 0) {
string = string.replace('%s', placeholders.shift());
}
return string;
}
EDIT: Based on lexith's answer, we can avoid the explicit loop:
function replaceStr(string, ...placeholders) {
var count = 0;
return string.replace(/%s/g, () => placeholders[count++]);
}
If hope you want to have custom logger function.
console.log can replace %s, with below approach your custom function gets full feature set of console.log and its more efficient.
function myLogger() {
if(logEnabled) {
// you can play with arguments for any customisation's
// arguments[0] is first string
// prepend date in log arguments[0] = (new Date().toString()) + arguments[0] ;
console.log.apply(console, arguments);
}
}
function replaceStr(string, ...placeholders) {
const replaced = string.replace(/%s/g, () => placeholders.shift());
return [replaced, ...placeholders].join(' ');
}
This will append any remaining placeholders to the string to more accurately replicate console.log.

javascript - convert function into variable

I googled a bit and it seems I either don't know what I'm asking or this isn't possible. I think it's probably the former.
If I have an object
obj = {
func : function(){
return 'hello';
}
}
and I normally do alert(obj.func()) I of course get "hello"
But if I wanted to have obj.func be simply a variable, is that possible somehow? I won't ever pass parameters to the function, I just want to reference its return value as a plain variable like alert(obj.func), not a function call.
Thanks.
Try this :
obj = {
func : (function(){
return 'hello';
})()
}
Yes, thats easy!
var obj = {
func : 'hello'
};
alert(obj.func);
see this working fiddle
if you want it to be a calculated value or sth. you can still let it be a function but callable like a simple property:
var obj = {
func : (function(){return 'hello';})()
};
What you are talking about is a getter : it is a function that works as a property.
It is standard since javascript 1.8.5, which means older browser won't handle it.
The syntax is as follow, using your example :
obj = {
get func() { return "hello" ; }
};
// use like this :
console.log(obj.func);
Most likely you will want to define a setter also : this is also a function behaving
like a property. The syntax will be :
obj = {
get func() { return this._innerText ; },
set func(txt) { this._innerText = txt ; },
_innerText : "hello"
};
console.log(obj.func) ; // output is hello
obj.func = "godd bye" ;
console.log(obj.func) ; // output is good bye
Obviously, as often with simple example, this one is of no big use:
Let us see a degree to radian converter using a getter / setter :
var Angle = {
get degree () { return this._degree ; },
set degree (dg) { this._degree = dg ; },
get radian () { return 2*Math.PI*this.degree/360 ; },
set radian (rd) { this._degree = rd * 360 / (2*Math.PI) ; },
_degree : 0
} ;
// you can use :
Angle.radian = Math.PI / 2;
console.log ( Angle.degree ); // -->> output is 90
Angle.degree=45 ;
console.log(Angle.radian) ; // --> output is 0.7853... which is PI/4
You might also have a look on Object.defineProperty, which allows to define both standard properties, and getters/setters, but with more option, especially the option to 'hide' a property, which allows it not to be enumerated.
For more information :
https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Operators/get
https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Operators/set
https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/Object/defineProperty
var varFunc = function() { alert("hello"); }
varFunc();

Categories

Resources