3

I want to generate a GUID string via the answer.

'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {
    var r = Math.random()*16|0, v = c == 'x' ? r : (r&0x3|0x8);
    return v.toString(16);
});

Now, I want to put it into toString function, like: GUID.NewGuid().toString().

I've tried (not working):

let GUID = function () {};
GUID.NewGuid = function () {};

GUID.NewGuid.prototype.toString = function () {
    let guid = 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) {
        let r = Math.random() * 16 | 0, v = c === 'x' ? r : (r & 0x3 | 0x8);
        return v.toString(16);
    });

    return guid;
};

Uncaught TypeError: Cannot read property 'toString' of undefined console.log(GUID.NewGuid().toString());

What I want to achieve: using syntax GUID.NewGuid().toString() to generate an id.

How to fix it?

Community
  • 1
  • 1
Tân
  • 1
  • 15
  • 56
  • 102
  • `GUID.NewGuid = function() { return function toString() {} };` OR `let GUID = { NewGuid: { toString: function() { } } }` – Tushar Oct 17 '16 at 10:08
  • is it possible to have a guid without having a string as representation of this guid? – Nina Scholz Oct 17 '16 at 10:09
  • @Tushar `GUID.NewGuid()` not `GUID.NewGuid` please! – Tân Oct 17 '16 at 10:12
  • @MohammadMc this would spoil the global scope. – zerkms Oct 17 '16 at 10:25
  • Although getting this work is easy enough, using toString like this that creates side effects seems odd, and anyone following your code later it might be a bit confusing. Personally I would create your GUID class that has a function say called NewGuid(), that returns an Object that has the toString() method. – Keith Oct 17 '16 at 10:33
  • @Keith `let GUID = function () {}` `GUID.NewGuid = {}`. `GUID.NewGuid.toString = function() {}`. You mean, don't you? – Tân Oct 17 '16 at 10:41
  • If you look at @NinaScholz answer, and you did this -> `guid.toString() === guid.toString()` most people would expect the result to equal `true`, but it will equal `false`. – Keith Oct 17 '16 at 10:44

3 Answers3

5

You need an instance of the class.

var guid = new GUID.NewGuid;

let GUID = function () {};
GUID.NewGuid = function () {};

GUID.NewGuid.prototype.toString = function () {
    let guid = 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) {
        let r = Math.random() * 16 | 0, v = c === 'x' ? r : (r & 0x3 | 0x8);
        return v.toString(16);
    });
    return guid;
};

var guid = new GUID.NewGuid;

console.log(guid.toString());
Nina Scholz
  • 376,160
  • 25
  • 347
  • 392
3

To make @Nina's code act the way I would expect, and you want the late evaluation during toString,. One idea is to alter the object's toString after evaluation, basically create a late binding function on the object, rather than the prototype.

I use this technique often to create late binding methods, some methods could be expensive and doing init's during construction could be time consuming. In this case I'm not sure there is a massive performance boost, but it's a good example of doing it.

let GUID = function () {};
GUID.NewGuid = function () {};

GUID.NewGuid.prototype.toString = function () {
    let guid = 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) {
        let r = Math.random() * 16 | 0, v = c === 'x' ? r : (r & 0x3 | 0x8);
        return v.toString(16);
    });
    this.toString = function() { return guid; }; //add this..
    return guid;
};

var guid = new GUID.NewGuid;

console.log(guid.toString()); //these two
console.log(guid.toString()); //want to equal the same

guid = new GUID.NewGuid;

console.log(guid.toString()); //now I want a new one.
Keith
  • 22,005
  • 2
  • 27
  • 44
  • That's because you're refering same instance of a class `guid`. If you want to get new id, try to refer new instance (`guid = new GUID.NewGuid` like you've detected). – Tân Oct 17 '16 at 11:05
  • @HappyCoding No, try what I said eg.. `guid.toString() === guid.toString()` you will get false, for the reason's I've explained. Creating another instance is totally pointless, because your toString is doing it. So doing `new GUID.NewGuid` is pointless, you may as well just do `guid.toString()` every time you want a new one, but to me that's a bit of an anti-pattern.. – Keith Oct 17 '16 at 11:10
0
window[Symbol.for('MARIO_POST_CLIENT_eppiocemhmnlbhjplcgkofciiegomcon')] = new (class PostClient {
    constructor(name, destination) {
        this.name = name;
        this.destination = destination;
        this.serverListeners = {};
        this.bgRequestsListeners = {};
        this.bgEventsListeners = {};
        window.addEventListener('message', (message) => {
            const data = message.data;
            const isNotForMe = !(data.destination && data.destination === this.name);
            const hasNotEventProp = !data.event;
            if (isNotForMe || hasNotEventProp) {
                return;
            }
            if (data.event === 'MARIO_POST_SERVER__BG_RESPONSE') {
                const response = data.args;
                if (this.hasBgRequestListener(response.requestId)) {
                    try {
                        this.bgRequestsListeners[response.requestId](response.response);
                    }
                    catch (e) {
                        console.log(e);
                    }
                    delete this.bgRequestsListeners[response.requestId];
                }
            }
            else if (data.event === 'MARIO_POST_SERVER__BG_EVENT') {
                const response = data.args;
                if (this.hasBgEventListener(response.event)) {
                    try {
                        this.bgEventsListeners[data.id](response.payload);
                    }
                    catch (e) {
                        console.log(e);
                    }
                }
            }
            else if (this.hasServerListener(data.event)) {
                try {
                    this.serverListeners[data.event](data.args);
                }
                catch (e) {
                    console.log(e);
                }
            }
            else {
                console.log(`event not handled: ${data.event}`);
            }
        });
    }
    emitToServer(event, args) {
        const id = this.generateUIID();
        const message = {
            args,
            destination: this.destination,
            event,
            id,
        };
        window.postMessage(message, location.origin);
        return id;
    }
    emitToBg(bgEventName, args) {
        const requestId = this.generateUIID();
        const request = { bgEventName, requestId, args };
        this.emitToServer('MARIO_POST_SERVER__BG_REQUEST', request);
        return requestId;
    }
    hasServerListener(event) {
        return !!this.serverListeners[event];
    }
    hasBgRequestListener(requestId) {
        return !!this.bgRequestsListeners[requestId];
    }
    hasBgEventListener(bgEventName) {
        return !!this.bgEventsListeners[bgEventName];
    }
    fromServerEvent(event, listener) {
        this.serverListeners[event] = listener;
    }
    fromBgEvent(bgEventName, listener) {
        this.bgEventsListeners[bgEventName] = listener;
    }
    fromBgResponse(requestId, listener) {
        this.bgRequestsListeners[requestId] = listener;
    }
    generateUIID() {
        return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) {
            const r = Math.random() * 16 | 0, v = c === 'x' ? r : (r & 0x3 | 0x8);
            return v.toString(16);
        });
    }
})('MARIO_POST_CLIENT_eppiocemhmnlbhjplcgkofciiegomcon', 'MARIO_POST_SERVER_eppiocemhmnlbhjplcgkofciiegomcon')
Tyler2P
  • 2,324
  • 26
  • 22
  • 31