What is the problem?
var yie = Object.create({}, {
'currentDoAction': {
value: null,
enumerable: true,
writeable: true
},
'success': {
value: function(result) {
this.currentDoAction = "should be changed";
console.log(this.currentDoAction); // prints out null ... why ?
},
enumerable: true,
writeable: true,
}
});
see the comment in the success function where this.currentDoAction still appears to be null even though it should be changed in the line before.
The problem is that you've misspelled writable (nb: no "e"), so that property key is ignored and the default value of writable: false is used instead.
See http://jsfiddle.net/szLju/ for a working version.
One problem I can see is that you have a trailing comma and some browsers don't like this:
writeable: true,
^
Related
according to MDN, when using Object.defineProperty(), its third argument is a descriptor with some optional keys, such as
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.
Defaults to false.
enumerable
true if and only if this property shows up during enumeration of the properties on the corresponding object.
Defaults to false.
...
I'd like to ask what does the defaults to false above mean?
I think it means that if I don't specify that key's value, it will be set to the default value, which is false, but when I try it in Chrome, it turns out to be as follows:
Object.getOwnPropertyDescriptor(o, 'a')
> {value: "c", writable: false, enumerable: true, configurable: true}
Object.defineProperty(o, 'a', {'enumerable': false})
> {a: "c"}
Object.getOwnPropertyDescriptor(o, 'a')
> {value: "c", writable: false, enumerable: false, configurable: true}
Apparently my descriptor missed the key configurable, but this attribute was not set to false.
Thanks for your help!
Quoting the same MDN article:
When the property already exists, Object.defineProperty() attempts to modify the property according to the values in the descriptor and the object's current configuration.
Since o.a already exists, Object.defineProperty() modifies the property with provided descriptor instead of defining it from scratch. In this case it only overwrites the keys you provide.
You can see the defaults in action by defining a new property.
var o = {}
> undefined
Object.defineProperty(o, 'a', {})
> {a: undefined}
Object.getOwnPropertyDescriptor(o, 'a')
> {value: undefined, writable: false, enumerable: false, configurable: false}
I apologize in advance if this has been asked elsewhere or if I have missed something important in the docs, well, but I need to ask this:
Let's say an object is being created without defining the respective properties
cons objA = Object.create({
init(text) {
this.text = text;
}
});
or an object is being created and the respective property has been declared in the properties object
const objB = Object.create({
init(text) {
this.text = text;
}
}, {
text: {
value: '',
writable: true
}
});
I understand that defining properties in the propertiesObject of Object.create helps defining and providing better contracts,
but
do these two scenarios vary in respect to the text property?
Yes, they vary - there is difference between a and b results
const a = Object.create({
init(text) {
this.text = text;
}
});
const b = Object.create({
init(text) {
this.text = text;
}
}, {
text: {
value: '',
writable: true
}
});
console.log(Object.getOwnPropertyNames(a))
console.log(Object.getOwnPropertyNames(b))
a.init('a text');
b.init('b text');
console.log(Object.getOwnPropertyDescriptor(a, 'text'))
console.log(Object.getOwnPropertyDescriptor(b, 'text'))
a returns:
{
"value": "a text",
"writable": true,
"enumerable": true,
"configurable": true
}
b returns:
{
"value": "b text",
"writable": true,
"enumerable": false,
"configurable": false
}
By default property is enumerable and configurable unless you define property by Object.defineProperty or Object.create. You can define them as you did with writable.
Enumerable works in certain object-property enumerations, such as the for..in.
Configurable means that you cannot use Object.defineProperty again on this property (there will be Cannot redefine property: text error).
Other than that - before you use init() - a object will have undefined text property (that is not enumerable, not configurable, writable) and object b will not have any property.
I'm fiddling around with a library called bcoin for node. Running the following code:
chain.on('block', function(block) {
console.log('Connected block to blockchain:');
block.txs.forEach(function(t) {
t.inputs.forEach(function(i) {
console.log(typeof i, i);
console.log(JSON.stringify(i));
});
});
});
This is the response I'm getting:
Connected block to blockchain:
object { type: 'coinbase',
subtype: null,
address: null,
script: <Script: 486604799 676>,
witness: <Witness: >,
redeem: null,
sequence: 4294967295,
prevout: <Outpoint: 0000000000000000000000000000000000000000000000000000000000000000/4294967295>,
coin: null }
{"prevout":{"hash":"0000000000000000000000000000000000000000000000000000000000000000","index":4294967295},"script":"04ffff001d02a402","witness":"00","sequence":4294967295,"address":null}
Notice that even though the attribute type for example, is shown when we print i, that attribute does not exist when we JSON.stringify the object. If I tried to console.log(i.type) I'd get undefined.
How is that possible? And what is a good way of debugging what's going on with an object?
JSON.stringify will only includes enumerable properties that are not functions.
So if you define a property and set as non-enumerable, it will not be a part of JSON string.
var obj = {
a: 'test'
};
// Non-enumerable property
Object.defineProperty(obj, 'type', {
enumerable: false,
value: 'Test'
});
// Get property
Object.defineProperty(obj, 'type2', {
get: function(){
return 'Test 2'
}
});
console.log(JSON.stringify(obj), obj);
console.log(obj.type, obj.type2)
I'm trying to add functionality to the format function but there is something wrong with my code:
Object.defineProperty(Intl.NumberFormat.prototype, "format", { value: function(){
//your logic here
let orig = Intl.NumberFormat.prototype
console.log(orig);// does not remember the original proto
}, configurable: true } );
What am I missing?
You basically catch the property itself. You want to get the original one so before it is overriden, and you may store its subobject references too through copying them:
{
let orig = Object.assign({}, Intl.NumberFormat.prototype);
Object.defineProperty(Intl.NumberFormat.prototype, "format", { value: function(){
//your logic here
console.log(orig);// does remember the original proto
}, configurable: true } );
}
I am trying to use javascript inheritance in my code. Following is the jsfiddle for the same.
http://jsfiddle.net/Fetsz/3/
var baseObject = Object.create(Object, {
// this works as an instance variable for derived objects
name: {
writable: true,
configurable: true,
enumerable: true,
value: null
},
// this should act as instance variable for derived objects
values: {
writable: true,
configurable: true,
enumerable: true,
value: []
},
displayAlert: {
value: function (){
alert("Alert from base object");
}
}
});
var derivedObj1 = Object.create(baseObject, {});
var derivedObj2 = Object.create(baseObject, {});
function displayValues (obj) {
alert("values for " + obj.name + "\n" + JSON.stringify(obj.values));
};
$(document).ready(function(){
derivedObj1.name = "Object 1";
derivedObj2.name = "Object 2";
derivedObj1.values.push("DO1 element");
derivedObj2.values.push("DO2 element");
derivedObj1.displayAlert();
// should display values added only for derivedObj1
displayValues(derivedObj1);
// should display values added only for derivedObj2
displayValues(derivedObj2);
});
I also checked following question which nicely explains why my code doesn't work. Javascript Inheritance: Parent's array variable retains value
I need to have an array member variable in every derived class which will contain certain values. I was trying to achieve the same by adding array in base class. As mentioned in above question, to achieve the same, I will have to add array member to each derived class. Is there any other way to achieve this without modifying every derived class?
When they are created, both derivedObj1.values and derivedObj2.values point to the same array object. If you were to first reassign each one using derivedObj1.values = [];, in the same way as you are reassigning the name property, your code would behave as expected.
Instead of adding the values property to the original baseObject, you could create an init method that adds an array to the instance:
var baseObject = Object.create(Object, {
// this works as an instance variable for derived objects
name: {
writable: true,
configurable: true,
enumerable: true,
value: null
},
// this should act as instance variable for derived objects
init: {
writable: true,
configurable: true,
enumerable: true,
value: function(){
this.values = [];
}
},
displayAlert: {
value: function (){
alert("Alert from base object");
}
}
});
var derivedObj1 = Object.create(baseObject, {});
derivedObj1.init();
var derivedObj2 = Object.create(baseObject, {});
derivedObj2.init();
Your variables can't be on the prototype if you don't want them to be shared by all instances. You could create a second object with just the property definition for the array,and pass it as the second parameter to Object.create:
var arrDef = {
values: {
writable: true,
configurable: true,
enumerable: true,
value: []
}
}
var derivedObj1 = Object.create(baseObject, arrDef);
var derivedObj2 = Object.create(baseObject, arrDef);