bantya bantya - 3 months ago 8
Javascript Question

Object.defineProperty or .prototype?

I've seen two different techniques of implementing non-native features in javascript,
First is:

if (!String.prototype.startsWith) {
Object.defineProperty(String.prototype, 'startsWith', {
enumerable: false,
configurable: false,
writable: false,
value: function(searchString, position) {
position = position || 0;
return this.lastIndexOf(searchString, position) === position;
}
});
}


and Second is:

String.prototype.startsWith = function(searchString, position) {
position = position || 0;
return this.lastIndexOf(searchString, position) === position;
}


I know that the second one is used to attach any method to the prototype chain of a particular standard built-in objects, but first technique is new to me.
Can anybody explain what is the difference between them, why one is used and why one not and what are their significances.

Answer

In two cases you are adding a new property 'startsWith' in String.prototype.

First differs from the second in this cases:

You can configure the property to be enumerable, writable and configurable.

Writable - true means that you can change its value by assigning any value. If false - you can't change the value

Object.defineProperty(String.prototype, 'startsWith', {
        enumerable: false,
        configurable: false,
        writable: false, // Set to False
        value: function(searchString, position) {
            position = position || 0;
            return this.lastIndexOf(searchString, position) === position;
        }
    });

var test = new String('Test');

test.startsWith = 'New Value';
console.log(test.startsWith); // It still have the previous value in non strict mode

Enumerable - true means that it will be seen in the for in loop.

Object.defineProperty(String.prototype, 'startsWith', {
        enumerable: true, // Set to True
        configurable: false,
        writable: false, 
        value: function(searchString, position) {
            position = position || 0;
            return this.lastIndexOf(searchString, position) === position;
        }
    });

var test = new String('Test');

for(var key in test){
   console.log(key)  ;
}

Configurable - true if and only if the type of this property descriptor may be changed and if the property may be deleted from the corresponding object.

Object.defineProperty(String.prototype, 'startsWith', {
            enumerable: false,
            configurable: false, // Set to False
            writable: false, 
            value: function(searchString, position) {
                position = position || 0;
                return this.lastIndexOf(searchString, position) === position;
            }
        });

    
    delete String.prototype.startsWith; // It will not delete the property
    console.log(String.prototype.startsWith);

And one advice to you, don't change the prototypes of build in types.