Why is it Object.defineProperty() rather than this.defineProperty() (for objects)?
It's to avoid collisions - in general, issues with objects that do not have the property with the value that you expect.
Objects in JS are often used as key-value-maps, and the keys can be arbitrary strings - for example __defineGetter__
, hasOwnProperty
or something less special. Now when you want to invoke such a function on an unknown object - like hasOwnProperty
is often used in generic enumeration functions, where any JSON might be passed in - you can never be sure whether you got a overwritten property (that might not even be a function) or the original which you want, or whether the object inherits the property at all. To avoid this issue (or also this IE bug), you'd have to use Object.prototype.hasOwnProperty.call
- that is ugly.
So, namespacing all those functions on Object
is only useful, it's a cleaner API that separates the reflection methods from the object's application interface. This also helps optimisation (simplifying static analysis) and makes it easier to restrict access to the reflection API in sandboxes - at least that was the design idea.
You might be happy to have a defineProperty
around in the prototype, but you can only use it safely when working with known objects. If you still want it (as you know when to use and when not), you could use
Object.defineProperty(Object.prototype, "defineProperty", {
writable: true,
enumberable: false,
value: function(prop, descr) {
return Object.defineProperty(this, prop, descr);
}
});
Object.defineproperty() vs Object.defineproperties()
As you noticed, Object.defineProperty
can't handle multiple properties, it takes the target object, one property name, and one descriptor.
On the other hand, Object.defineProperties
takes the target object, and another object whose every key is a property name and every value is the corresponding descriptor, which allows to define multiple properties at once.
Nothing prevents you from using Object.defineProperties
even for single properties, it's just a bit more work (and maybe less readable code?) because you have to build the object which contains the properties definition.
Object.defineProperty vs vanilla property
Yes, they behave the same when
- there is no
bar
property infoo
(not even an inherited one), so a new one is created, or - there is a
bar
property that has thewritable
andconfigurable
attributes set totrue
However, if neither of those is given, the two indeed produce slightly different results.
defineProperty
does not consider inherited properties and their descriptors- If the existing (possibly inherited) property is an accessor, the assignment will try to call the setter (and fail if none exists), while
definePropery
will overwrite the property with the data descriptor (or fail if it is an own, non-configurable one) - If an existing inherited property is a data property, the assignment will fail if
writable
is false, or create a new own property if true, like thedefineProperty
always does - If an existing own property is a data property, the assignment will fail if
writable
is false, or set the new value if true, whiledefineOwnProperty
will fail iffconfigurable
is false and overwrite the attributes otherwise.
Considering the basic scenario of usage
If by "basic usage" you mean no usage of fancy property attributes, then yes they are equivalent. Yet you should just use the simple assignments, for they are easier to read and faster to execute.
Can we fall back to vanilla in pre-ES6 applications
Notice that full support of defineProperty
comes with ES5, so unless you need to consider pre-ES5 (old IE) browsers you wouldn't care at all.
when do you use Object.defineProperty()
Object.defineProperty
is mainly used to set properties with specific property descriptors (e.g. read-only (constants), enumerability (to not show a property in a for (.. in ..)
loop, getters, setters).
"use strict";
var myObj = {}; // Create object
// Set property (+descriptor)
Object.defineProperty(myObj, 'myprop', {
value: 5,
writable: false
});
console.log(myObj.myprop);// 5
myObj.myprop = 1; // In strict mode: TypeError: myObj.myprop is read-only
Example
This method extends the Object
prototype with a property. Only the getter is defined, and the enumerability is set to false
.
Object.defineProperty(Object.prototype, '__CLASS__', {
get: function() {
return Object.prototype.toString.call(this);
},
enumerable: false // = Default
});
Object.keys({}); // []
console.log([].__CLASS__); // "[object Array]"
Why does object.defineproperty not add the property to the object?
Object.assign only copies enumerable own properties.
Object.defineProperty defines non enumerable properties unless the descriptor overrides the default value (false
) for enumerable
.
var a ={a:1}var b={a:5,b:6}b['d']=33Object.defineProperty(b,'c',{ value:'eee', enumerable: true})var t ={}Object.assign(t,a,b)console.log(t)
Object.defineProperty or .prototype?
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
Related Topics
Http Status Code 401 Even Though I'm Sending Credentials in the Request
Highlight Selected Node, Its Links, and Its Children in a D3 Force Directed Graph
JavaScript Parser in JavaScript
Settimeout Ignores Timeout? (Fires Immediately)
How to Stop Event Bubbling on Checkbox Click
How to Develop Desktop Apps Using HTML/Css/Javascript
Change the Content of a Div Based on Selection from Dropdown Menu
How Does Inline JavaScript (In HTML) Work
How to Filter Input Type="File" Dialog by Specific File Type
Why Is It Object.Defineproperty() Rather Than This.Defineproperty() (For Objects)
How to Remove a Buggy Service Worker, or Implement a "Kill Switch"
How to Solve 'Redirect Has Been Blocked by Cors Policy: No 'Access-Control-Allow-Origin' Header'
Uploading Image to Amazon S3 with HTML, JavaScript & Jquery with Ajax Request (No PHP)
Removing Page Title and Date When Printing Web Page (With CSS)