4

Below there's a function that returns the string depending on a current language, for example if the language is "it"

var currLang = "it";
var language = (function () {
  /*this.uppercase = function(){
    // the following is more like a pseudo since makes no sense:
    return this.toUpperCase(); // I mean, it's wrong... I know :(
  };*/
  return {
    it : {
      hi : "ciao"
    },
    es : {
      hi : "ola"
    }
  }[ currLang ];  
})();


console.log( language.hi ); // ciao
console.log( language.hi.toUpperCase() ); // CIAO

Above I'm happy to use it like it is, chaining the JS's vanilla String prototype toUpperCase, but I was just wondering:
how to chain a method we created... like .toUpperCase or a custom one like .toFirstUppercase() ? For example:

language.hi.toFirstUppercase() 

but keeping our toFirstUppercase inside the language function?

My problem is that language.hi already returns a string, I know that .toUpperCase() operates on the object "String".toUpperCase() but how to make a custom method inside my app that will help to achieve the same?

Please, if the question is not clear I'd like to improve it so let me know! Thx for any suggestion

Ginnani
  • 325
  • 1
  • 5
  • 19
  • See [Function that can return a value and also act as an object](http://stackoverflow.com/q/27724654/1529630) – Oriol May 02 '15 at 00:31
  • 1
    possible duplicate of [javascript: add method to string class](http://stackoverflow.com/questions/8392035/javascript-add-method-to-string-class) – Downgoat May 02 '15 at 01:20

4 Answers4

1

Use prototypes and add a toFirstUpperCase method to the String.prototype object. This will instantiate an instance of the toFirstUpperCase closure function for every instance of String:

var currLang = "it";
var language = (function () {
  /*this.uppercase = function(){
    // the following is more like a pseudo since makes no sense:
    return this.toUpperCase(); // I mean, it's wrong... I know :(
  };*/
  return {
    it : {
      hi : "ciao"
    },
    es : {
      hi : "ola"
    }
  }[ currLang ];  
})();

String.prototype.toFirstUpperCase = function()
{
    return this[0].toUpperCase() + this.slice(1, this.length);
}


console.log( language.hi ); // ciao
console.log( language.hi.toUpperCase() ); // CIAO
console.log( language.hi.toFirstUpperCase() ); // Ciao
  • Yes, I know that, it would be like the JS's `toUpperCase _proto_`, just messing with the `window` prototypal namespace... but how to put that function `toFirstUppercase` **inside** our app? And allow it to be chainable? – Ginnani May 02 '15 at 01:15
  • 1
    1) It is chainable already because it returns a string. It will chain with other string methods that also return strings. 2) I don't know what you mean by "inside our app". You can add a currLang field to the string itself if you need to, or depend on a global variable or injected context to get that state value. Can you please be more specific with a concrete example of how you would like the API to look? –  May 02 '15 at 01:19
0
var currLang = "it";
var language = (function () {
  //You could also add it to the String.prototype so you could chain it with other methods:
  String.prototype.toFirstUppercase=function(){
    s = this;
    return s.length > 0 ? s.charAt(0).toUpperCase() + s.slice(1) : s;
  };
  return {
    it : {
      hi : "ciao"
    },
    es : {
      hi : "ola"
    }
  }[ currLang ];
})();
//and use it like this:
console.log(language.hi);        //ciao
console.log(language.hi.toFirstUppercase());  //Ciao

Another solution:

var currLang = "it";
var language = (function () {
    String.prototype.toFirstUpperCase = function(){
        return this[0].toUpperCase() + this.slice(1, this.length);
    };
    var hi;
    switch(currLang){
        case "it":
            hi = "ciao";
            break;
        case "es":
            hi = "ola";
            break;
        default:
            hi = "hello";
    }
    //simple
    //return hi;
    //object
    return {
        hi : hi
    };
})();
//use
console.log(language.hi);
console.log(language.hi.toFirstUpperCase());
alessandrio
  • 4,282
  • 2
  • 29
  • 40
  • Err... I like it more using Object notation instead of `switch / case`. Now my question again, how would you incorporate inside your app a method like `toFirstUppercase` that can be than used like `language.hi.toFirstUppercase()` ? – Ginnani May 02 '15 at 00:52
  • there!. using Object notation. :) – alessandrio May 02 '15 at 13:29
0

JavaScript doesn't have classes and other things like that, but I would do something like the following:

Creating an object

var Word = function (word) { 
    var _value = word; //Private variable, modify _value as needed

    Object.defineProperties(this, {
        'value': {
            enumerable  : true,
            get         : function (a) { return _value; },
            set         : function (a) { _value = a; }
        },
        //Functions
        'uppercase': {
            get         : function () { return _value.toUpperCase() }
        }
    });        
};

Then:

//...
'hi': new Word('ciao')
//...

Then:

language.it.hi.value; // ciao
language.it.hi.uppercase; // CIAO
Community
  • 1
  • 1
Downgoat
  • 13,771
  • 5
  • 46
  • 69
  • I see you answered this question twice... JavaScript has prototypal inheritance, and I think adding a `toFirstUpperCase` method to the `String.prototype` object will work just fine for the asker's specific use case. –  May 02 '15 at 01:18
  • 1
    @AlexanderPritchard Two different approaches though :) – Downgoat May 02 '15 at 01:19
  • I just noticed this and your other response as well. Thank you for the clarification. –  May 02 '15 at 01:22
0

JavaScript variables can be made using their constructor new Array(), new String(), etc. We can use this and then just add a function.

Using string as an object

Also, you can just add something to the string using the constructor:

var Word = function (word) {
    var _word = new String(word); // new String() is essential

    _word.toFirstUppercase = function () {
        return this.toUpperCase();
    };

    return _word;
};

Then:

//...
'hi': new Word('ciao')
//...

alert(language.it.hi); //'ciao'
alert(language.it.hi.toFirstUppercase); //'CIAO'

var Word = function (word) {
    var _word = new String(word); // new String() is essential

    _word.toFirstUppercase = function () {
        return this.toUpperCase();
    };

    return _word;
};

var currLang = "it";
var language = (function () {
  /*this.uppercase = function(){
    // the following is more like a pseudo since makes no sense:
    return this.toUpperCase(); // I mean, it's wrong... I know :(
  };*/
  return {
    it : {
      hi : new Word("ciao")
    },
    es : {
      hi : new Word("ola")
    }
  }[ currLang ];  
})();


console.log( language.hi ); // ciao
console.log( language.hi.toFirstUppercase() ); // CIAO
Community
  • 1
  • 1
Downgoat
  • 13,771
  • 5
  • 46
  • 69
  • 1
    Why not just use prototypal inheritance? Add the toFirstUpperCase method to the String.prototype object and there will be no need to wrap the string into an additional class. Also, `toFirstUppercase` in your example code is a function object and must be invoked, otherwise that `alert` might just print the contents of the function. –  May 02 '15 at 01:16
  • @AlexanderPritchard It wasn't so clear wether OP wanted to extend `String.prototype` or add a function *just* to the word. If OP wanted to extend `String.prototype`, **this question is a duplicate** – Downgoat May 02 '15 at 01:19
  • @AlexanderPritchard also if the OP is making an API, you wouldn't really want to be messing with `String.prototype` on end-user's page. – Downgoat May 02 '15 at 01:23
  • 1
    I agree with you on all cases. I guess we'll just have to wait and see what OP is really trying to accomplish here :) –  May 02 '15 at 01:25