Search code examples
javascriptstringobjectprototypedefineproperty

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.


Solution

  • 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.