2

Here's the code I'm working with at the moment:

Object.defineProperty(String.prototype, "testy", {
    get: function() {
        return this.string;
    },
    set: function(string) {
        this.string = string;
    }
});

console.log("tessfef3t".testy());

Before I would've used String.prototype.testy = function {}, however I've been told that using something similar to the the code above is the better way to do it. I'm not sure how that is meant to work but I haven't got that code to work yet.

Could someone show me how to correctly do what I'm doing?

Thanks

  • 2
    What do you expect `"tessfef3t".testy()` to be? – xdazz Aug 13 '12 at 13:07
  • I expect it to log `tessfef3t` to the console (so the string is actually unchanged in this case, but I need an example to show me what I'm doing wrong). –  Aug 13 '12 at 13:07
  • 4
    You're trying to invoke the property as though it was a function... but it's not. Also, `this` is going to be the temporary `String` wrapper, so you're adding a property that will never really be usable. Finally, strings are immutable. You can't change them. You can only replace them on the variables/properties that reference them. –  Aug 13 '12 at 13:12

3 Answers3

2

testy is kind of a "fake" property -- it has no value of its own, but setting or getting its value will invoke its set and get functions. You can use it like:

var foo = new String();

// this invokes the setter and sets foo.string to 5:
foo.testy = 5; 

// this invokes the getter and prints the value of foo.string
console.log(foo.testy); 

// this prints 5, because foo.string has been set by the setter
console.log(foo.string);

EDIT:

Now I see your comment about what you actually want to happen. It's not possible to alter the value of a string object, because strings are immutable. You'd have to destroy the string object and replace it with a new one, which is not possible within the object's own member function.

apsillers
  • 112,806
  • 17
  • 235
  • 239
  • Ah, I think I understand how they work now. Thanks for the example! :) Only thing is, what I'm aiming to do is extend the `String` prototype and I've been told getters and setters are better for me to use in that case but I'm not sure what I should do. –  Aug 13 '12 at 13:14
  • @Fike Which approach is better depends largely on what you *actually* want to do. I read your comment and added an edit. You can't modify the value of a string object, because they are immutable, but you can return *new* strings that are trasformations of the original string. Because of this, you are probably better off not using a getter/setter approach. – apsillers Aug 13 '12 at 13:22
1

If all you're doing in your getter and setter is setting a property that is not used elsewhere and there's no other processing then you gain nothing by using a getter and setter so you're better off with your original approach. Furthermore, you won't be able to retrieve a property you set on a string anyway. A string value in JavaScript (which is what a string literal such as "foo" creates, and is the only kind of string that is generally useful) is not an object so attempting to accessing a property requires special handling: effectively a temporary String object is created and thrown away immediately afterwards.

Finally, another major disadvantage of getters and setters is that they are specified in ECMAScript 5 and as such are only available in relatively recent browsers. They aren't implemented in IE < 9, for example.

Tim Down
  • 318,141
  • 75
  • 454
  • 536
1

This worked fine for me:

Object.defineProperty(String.prototype, "byteLength", {
    get: function() {
        var str = "" + this; // Get internal value
        // Compute size in actual bytes vs Unicode characters
        // per http://stackoverflow.com/a/23329386/912236
        for (var b = str.length, c = str.length - 1; 0 <= c; c--) {
            var a = str.charCodeAt(c);
            127 < a && 2047 >= a ? b++ : 2047 < a && 65535 >= a && (b += 2);
            56320 <= a && 57343 >= a && c--;
        }
        return b;
    }
});

> "Hello".byteLength
< 5

Orwellophile
  • 13,235
  • 3
  • 69
  • 45
  • Nice example! (It only demonstrates the `get` feature, but everybody can imagine the rest.) – rplantiko Apr 19 '15 at 14:12
  • hmmm... are there any existing native types with a `set`? the idea of setting a basic type just seems wrong. fine for HTMLElement an what not, but can't see myself using String.language = "Norwegian" – Orwellophile Apr 19 '15 at 21:52