I was looking at the example on the MDN pages about Inheritance Revisited and thought it would be nice to have the doSomething methods actually do something. So I started out with the following code, based on the example:
function A(a) { this.varA = a };
A.prototype = { varA: null, doSomething: function() { console.log('do something with ' + this.varA) } };
function B(a, b) {
A.call(this, a);
this.varB = b;
};
B.prototype = Object.create(new A(), {
varB: { value: null, enumerable: true, configurable: true, writeable: true },
doSomething: { value: function() {
A.prototype.doSomething.apply(this, arguments);
console.log("do something with " + this.varB);
}, enumerable: true, configurable: true, writeable: true}
});
var b = new B('a', 'b');
b.doSomething();
I copy and pasted the code into the Chrome console and expected to be seeing
do something with a
do something with b
but instead I got
do something with a
do something with null
What am I overlooking here? Shouldn't the call to "new B" result in the constructor which was defined above (function B(...)) being called? And if the constructor is called, shouldn't b.varB have a value? How do I need to change the example so the output is as expected?
Accidentally you specified varB as being non-writable and hence the assignment this.varB = b failed (or was ignored).
writeable: true should be spelled writable: true (without e). By default, properties defined using the a property descriptor are non-writable.
So the whole descriptor becomes:
varB: { value: null, enumerable: true, configurable: true, writable: true }
Since you are assigning a value inside the constructor function anyway, you don't really have to use the descriptor though.
More information: MDN - Object.defineProperty.
Related
Somehow I can read the property of a getter, but I can't delete it.
(I can delete getters/setters defined w/o using Object.defineProperties)
var hello = {
get num() {
return 123;
}
}
delete hello.num;
// returns true
However,
var hello = {};
Object.defineProperties(hello, {
num: {
get() {
return 123;
}
}
}
delete hello.num;
// returns false
The problem is that using the .defineProperties their is a property called writable
By default, it is set to False set it to true there is also a property called configurable
set it to true as well You can see the following code example to achieve this
'use strict'
Object.defineProperty(window, 'hello',{
get: ()=>"hello to you!",
configurable: true //make this true
and for the writeable property you can set it like this:
Object.defineProperty(obj, 'key', {
enumerable: false,
configurable: True,
writable: True,
value: 'static'
});
I'm trying to get the following code to work.
Array.prototype.test = {
func: function() {
console.log(this);
return this;
}
};
Then when I run the following.
[].test.func();
The problem is the this within that function is the object Array.prototype.test NOT the array that I passed in.
I feel like there has to be way to do this without setting Array.prototype.test to a function and having to call it like so [].test().func();.
Chai uses this type of syntax quite a bit. So I'm assuming it's possible.
How can I get this to work as I'm expecting it to?
JavaSript doesn't really have a good way to access that.
You could use a getter for test that returns a function with bound methods.
Object.defineProperty(Array.prototype, 'test', {
configurable: true,
enumerable: false,
get: function() {
return {
func: function() {
console.log(this);
return this;
}.bind(this)
};
}
});
[].test.func();
But it's pretty convoluted compared to just using .testFunc.
// Using Object.defineProperty to avoid enumerable prototype properties.
Object.defineProperty(Array.prototype, 'testFunc', {
configurable: true,
enumerable: false,
writable: true,
value: function() {
console.log(this);
return this;
}
});
[].testFunc();
See How does the expect().to.be.true work in Chai? to see they do roughly the same thing.
Trying to define a hashCode method on Object.prototype as well as String.prototype and Number.prototype. I'm defining the prototype methods using:
Object.defineProperty(Object.prototype, 'hashCode', {
value:function() {/*code*/},
enumerable:false
});
String.prototype.hashCode = function() {/*code*/};
Number.prototype.hashCode = function() {/*code*/};
When I create a number or string with any of ('', new String(), 3, new Number()), and call hashCode on the instance, the Object.prototype.hashCode method always runs instead of String.prototype.hashCode or Number.prototype.hashCode.
What's wrong?
Make the property descriptor writable: true or it will be inherited as non-writable when writing that property on objects that inherit it.
http://jsfiddle.net/5ox1a0f2 – squint
Object.defineProperty(Object.prototype, 'hashCode', {
value:function() {console.log('object')},
enumerable:false,
writable:true
});
String.prototype.hashCode = function() {console.log('string')};
Number.prototype.hashCode = function() {console.log('number')};
4..hashCode()
Mixing property definitions and property assignments can lead to this kind of problems.
It works if you also use property definition in String.prototype and Number.prototype:
Object.defineProperty(Object.prototype, 'hashCode', {
value: function() {console.log('object')},
enumerable: false
});
Object.defineProperty(String.prototype, 'hashCode', {
value: function() {console.log('string')},
enumerable: false
});
Object.defineProperty(Number.prototype, 'hashCode', {
value: function() {console.log('number')},
enumerable: false
});
(4).hashCode(); // "number"
('').hashCode(); // "string"
However, if you are only using property definitions because you don't want enumerability, but don't care about configurability nor writability, it may be more convenient to define the methods via assignment, and then redefine the enumerability:
Object.prototype.hashCode = function() {console.log('object')};
String.prototype.hashCode = function() {console.log('string')};
Number.prototype.hashCode = function() {console.log('number')};
Object.defineProperty(Object.prototype, 'hashCode', {enumerable: false});
Object.defineProperty(String.prototype, 'hashCode', {enumerable: false});
Object.defineProperty(Number.prototype, 'hashCode', {enumerable: false});
(4).hashCode(); // "number"
('').hashCode(); // "string"
I need to know if is possible to make instances of a javascript class that has non-enumerable attributes, for example
// Constructor
function MyClass(a) {
Object.defineProperty(this, '_number', {
enumerable: false
});
this.number = a; // Call setter for '_number'
}
// Getters and setters for '_number'
Object.defineProperty(MyClass.prototype, 'number', {
get: function() {
return this._number;
},
set: function(n) {
// Validate 'n' here
this._number = n;
}
});
What I wanted this code to do is to define the property _number on any instance of MyClass, making it not enumerable so that instance private variables such as _number wouldn't be listed in, suppose, a for in structure. You would use the number getter/setter to alter the private variable _number.
I have tried declaring the _number and number properties both inside the constructor and on MyClass.prototype with no success...
Any help would be appreciated!
Your approach is fine, you just need to watch out for the other attribute values which default to false:
function MyClass(a) {
Object.defineProperty(this, '_number', {
value: 0, // better than `undefined`
writable: true, // important!
enumerable: false, // could be omitted
configurable: true // nice to have
});
this.number = a; // Call setter for '_number'
}
// Getters and setters for '_number'
Object.defineProperty(MyClass.prototype, 'number', {
get: function() {
return this._number;
},
set: function(n) {
// Validate 'n' here
this._number = n;
},
enumerable: true, // to get `.number` enumerated in the loop
configurable: true // nice to have
});
Please, help to understand why is the line obj['prop'] = 'zzz'; doesn't work and even shows error when "use strict"; is on and works fine when Object.defineProperty(obj, 'prop', {value:'zzz'}); is used? (While delete works absolutely fine)
//"use strict";
var obj = Object.defineProperties({}, {
prop: {
value: 'aaa',
writeable: true,
enumerable: true,
configurable: true
}
});
console.log(obj.prop);
obj['prop'] = 'zzz';
//Object.defineProperty(obj, 'prop', {value:'zzz'});
console.log(obj.prop);
//delete obj.prop;
//console.log(obj.prop);
Its writable, not writeable (notice no e in the middle).
See MDN: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/defineProperties#Parameters