Object.defineProperty or .prototype?
Asked Answered
M

1

21

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.

Mourant answered 15/8, 2016 at 19:8 Comment(3)
did you look up Object.defineProperty to attempt to understand how it works?Overpower
enumerable, configurable, and writable all default to false and thus are not necessary. In any case, the advantage of this is that, uhh, properties so defined are not enumerable, configurable, or writable, all of which you probably want.Calc
Yes, but found the official documentation on developer.mozilla.org slightly confusing. If we can add a property to prototype of particular standard built-in objects then what does defineProperty actually do, that was confusing part.Mourant
A
39

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.

Appropriate answered 15/8, 2016 at 19:14 Comment(3)
Okk, that means by usingdefineProperty, we can set the behavior of required property to what we want to be, is that right?Mourant
Yes you are right. If you will define a property and miss the writable, enumerable and configurable their values will be false by defaultAppropriate
Thanks for your demonstration with code, it is really a big help in understanding the scenario.. Thanks again..Mourant

© 2022 - 2024 — McMap. All rights reserved.