sprintf.js icon indicating copy to clipboard operation
sprintf.js copied to clipboard

Feature Request: Object.prototype.toString.apply Type

Open nyteshade opened this issue 7 years ago • 12 comments

For those who are working with things like [Symbol.toStringTag] or those who have previously and often used things like Object.prototype.toString.apply() an ability to get that value easily would also be nice

// Map %C, open to other values, to the "Class" of an object
const classOf = o => Object.prototype.toString.call(o).replace(/\[object (.*?)\]/, '$1')

classOf(/asdfads/) // 'RegExp'
classOf(34) // 'Number'
classOf("asdfasd") // 'String'
classOf(Object.prototype) // 'Object'
classOf(null) // 'Null'
classOf(undefined) // 'Undefined'

let o = {}
o[Symbol.toStringTag] = "My Very Special Object"
classOf(o) // 'My Very Special Object'

Use of the above for a %C sprintf would be like the following

sprintf('%C', /asdfasd/); // 'RegExp'
sprintf('This object is a %C', "asdfas"); // 'This object is a String'
// etc...

nyteshade avatar Oct 02 '17 00:10 nyteshade

Pull request and unit tests submitted. https://github.com/alexei/sprintf.js/pull/156

nyteshade avatar Oct 04 '17 03:10 nyteshade

Is %T not working for you?

alexei avatar Oct 04 '17 08:10 alexei

Granted, %T doesn't preserve the case (perhaps erroneously)

alexei avatar Oct 04 '17 08:10 alexei

typeof and Object.prototype.toString.call are two very different things. They will also return different values for the same objects.

nyteshade avatar Oct 04 '17 14:10 nyteshade

I know, see https://github.com/alexei/sprintf.js/blob/master/src/sprintf.js#L103

alexei avatar Oct 04 '17 14:10 alexei

NB: I edited your comment to strip my original message and your signature (which contains your email address and phone numbers)

alexei avatar Oct 04 '17 14:10 alexei

Thanks for that. Missed %T by the way. Nonetheless, you do not want to change the case because it prevents type.name comparisons.

The way I see it there are three choices.

  1. Altogether reject the PR
  2. Break backwards compatibility for those who’ve been using %T
  3. Add in mine as a going forward solution and potentially deprecate the other.

Ultimately it is your repo. :)

Advantages are being able to do things like

let type = sprintf(‘%C’, function () {}) Function.name === type

Also note that my PR allows the conversion of functions to their type, also used for classes, rather than evaluating them. Potentially another use case for both.

nyteshade avatar Oct 04 '17 14:10 nyteshade

I was indeed thinking this morning to leave the type as is and break backwards compatibility

alexei avatar Oct 04 '17 14:10 alexei

If you do, please allow functions and classes to be converted to type rather than being executed. There are real uses for that scenario. Especially when in conjunction with classes and Symbol.toStringTag.

You may wish to use my unit test or a variation thereof as well. Feel free. Forgot to add in the assert for a Function but you can do so if you keep it since it appears you might be modifying some stuff nonetheless.

nyteshade avatar Oct 04 '17 15:10 nyteshade

If you do, please allow functions and classes to be converted to type rather than being executed

I suppose you're talking about https://github.com/alexei/sprintf.js/pull/156/files#diff-13ed28d46a5f76f4d44561850bda81bbR61

alexei avatar Oct 04 '17 15:10 alexei

Yup. Again I defer to your choice. With the ability to use Symbols in code to specify custom return values for Object.prototype.toString.(call|apply), I have seen usage for this pattern increase in recent years.

nyteshade avatar Oct 04 '17 15:10 nyteshade

Regarding https://github.com/alexei/sprintf.js/issues/155#issuecomment-334185653 above:

Executing randomly submitted function values is a . . . hindrance to usage. If users cannot guarantee every value presented to sprintf-js is not tainted by being function reference, random exceptions happen.

I've been having to swap back to console.log repeatedly.

Oh dear, 7 years ago? (https://github.com/alexei/sprintf.js/commit/d84118bb4b4403eda124797e9613013aad26fdd8) We're stuck? Or can it be acknowledged as a mis-feature? Was there an obvious use case I'm ignorant of?

.

(edit) Your last comment in #157 mentions the topic.

tshinnic avatar Jan 30 '21 22:01 tshinnic