I looked around for how to use the Object.defineProperty
method, but couldn't find anything decent.
Someone gave me this snippet of code:
Object.defineProperty(player, "health", {
get: function () {
return 10 + ( player.level * 15 );
}
})
But I don't understand it. Mainly, the get
is what I can't get (pun intended). How does it work?
This question is related to
javascript
object
defineproperty
get
is a function that is called when you try to read the value player.health
, like in:
console.log(player.health);
It's effectively not much different than:
player.getHealth = function(){
return 10 + this.level*15;
}
console.log(player.getHealth());
The opposite of get is set, which would be used when you assign to the value. Since there is no setter, it seems that assigning to the player's health is not intended:
player.health = 5; // Doesn't do anything, since there is no set function defined
A very simple example:
var player = {_x000D_
level: 5_x000D_
};_x000D_
_x000D_
Object.defineProperty(player, "health", {_x000D_
get: function() {_x000D_
return 10 + (player.level * 15);_x000D_
}_x000D_
});_x000D_
_x000D_
console.log(player.health); // 85_x000D_
player.level++;_x000D_
console.log(player.health); // 100_x000D_
_x000D_
player.health = 5; // Does nothing_x000D_
console.log(player.health); // 100
_x000D_
Defines a new property directly on an object, or modifies an existing property on an object, and return the object.
Note: You call this method directly on the Object constructor rather than on an instance of type Object.
const object1 = {};
Object.defineProperty(object1, 'property1', {
value: 42,
writable: false, //If its false can't modify value using equal symbol
enumerable: false, // If its false can't able to get value in Object.keys and for in loop
configurable: false //if its false, can't able to modify value using defineproperty while writable in false
});
Simple explanation about define Property.
Example code: https://jsfiddle.net/manoj_antony32/pu5n61fs/
Basically, defineProperty
is a method that takes in 3 parameters - an object, a property, and a descriptor. What is happening in this particular call is the "health"
property of the player
object is getting assigned to 10 plus 15 times that player object's level.
Object.defineProperty(player, "health", {
get: function () {
return 10 + ( player.level * 15 );
}
});
Object.defineProperty
is used in order to make a new property on the player object. Object.defineProperty
is a function which is natively present in the JS runtime environemnt and takes the following arguments:
Object.defineProperty(obj, prop, descriptor)
The descriptor object is the interesting part. In here we can define the following things:
<boolean>
: If true
the property descriptor may be changed and the property may be deleted from the object. If configurable is false
the descriptor properties which are passed in Object.defineProperty
cannot be changed.<boolean>
: If true
the property may be overwritten using the assignment operator.<boolean>
: If true
the property can be iterated over in a for...in
loop. Also when using the Object.keys
function the key will be present. If the property is false
they will not be iterated over using a for..in
loop and not show up when using Object.keys
.<function>
: A function which is called whenever is the property is required. Instead of giving the direct value this function is called and the returned value is given as the value of the property<function>
: A function which is called whenever is the property is assigned. Instead of setting the direct value this function is called and the returned value is used to set the value of the property.const player = {_x000D_
level: 10_x000D_
};_x000D_
_x000D_
Object.defineProperty(player, "health", {_x000D_
configurable: true,_x000D_
enumerable: false,_x000D_
get: function() {_x000D_
console.log('Inside the get function');_x000D_
return 10 + (player.level * 15);_x000D_
}_x000D_
});_x000D_
_x000D_
console.log(player.health);_x000D_
// the get function is called and the return value is returned as a value_x000D_
_x000D_
for (let prop in player) {_x000D_
console.log(prop);_x000D_
// only prop is logged here, health is not logged because is not an iterable property._x000D_
// This is because we set the enumerable to false when defining the property_x000D_
}
_x000D_
Object.defineProperty(Array.prototype, "last", {_x000D_
get: function() {_x000D_
if (this[this.length -1] == undefined) { return [] }_x000D_
else { return this[this.length -1] }_x000D_
}_x000D_
});_x000D_
_x000D_
console.log([1,2,3,4].last) //returns 4
_x000D_
Object.defineProperty() is a global function..Its not available inside the function which declares the object otherwise.You'll have to use it statically...
import { CSSProperties } from 'react'_x000D_
import { BLACK, BLUE, GREY_DARK, WHITE } from '../colours'_x000D_
_x000D_
export const COLOR_ACCENT = BLUE_x000D_
export const COLOR_DEFAULT = BLACK_x000D_
export const FAMILY = "'Segoe UI', sans-serif"_x000D_
export const SIZE_LARGE = '26px'_x000D_
export const SIZE_MEDIUM = '20px'_x000D_
export const WEIGHT = 400_x000D_
_x000D_
type Font = {_x000D_
color: string,_x000D_
size: string,_x000D_
accent: Font,_x000D_
default: Font,_x000D_
light: Font,_x000D_
neutral: Font,_x000D_
xsmall: Font,_x000D_
small: Font,_x000D_
medium: Font,_x000D_
large: Font,_x000D_
xlarge: Font,_x000D_
xxlarge: Font_x000D_
} & (() => CSSProperties)_x000D_
_x000D_
function font (this: Font): CSSProperties {_x000D_
const css = {_x000D_
color: this.color,_x000D_
fontFamily: FAMILY,_x000D_
fontSize: this.size,_x000D_
fontWeight: WEIGHT_x000D_
}_x000D_
delete this.color_x000D_
delete this.size_x000D_
return css_x000D_
}_x000D_
_x000D_
const dp = (type: 'color' | 'size', name: string, value: string) => {_x000D_
Object.defineProperty(font, name, { get () {_x000D_
this[type] = value_x000D_
return this_x000D_
}})_x000D_
}_x000D_
_x000D_
dp('color', 'accent', COLOR_ACCENT)_x000D_
dp('color', 'default', COLOR_DEFAULT)_x000D_
dp('color', 'light', COLOR_LIGHT)_x000D_
dp('color', 'neutral', COLOR_NEUTRAL)_x000D_
dp('size', 'xsmall', SIZE_XSMALL)_x000D_
dp('size', 'small', SIZE_SMALL)_x000D_
dp('size', 'medium', SIZE_MEDIUM)_x000D_
_x000D_
export default font as Font
_x000D_
defineProperty is a method on Object which allow you to configure the properties to meet some criterias. Here is a simple example with an employee object with two properties firstName & lastName and append the two properties by overriding the toString method on the object.
var employee = {
firstName: "Jameel",
lastName: "Moideen"
};
employee.toString=function () {
return this.firstName + " " + this.lastName;
};
console.log(employee.toString());
You will get Output as : Jameel Moideen
I am going to change the same code by using defineProperty on the object
var employee = {
firstName: "Jameel",
lastName: "Moideen"
};
Object.defineProperty(employee, 'toString', {
value: function () {
return this.firstName + " " + this.lastName;
},
writable: true,
enumerable: true,
configurable: true
});
console.log(employee.toString());
The first parameter is the name of the object and then second parameter is name of the property we are adding , in our case it’s toString and then the last parameter is json object which have a value going to be a function and three parameters writable,enumerable and configurable.Right now I just declared everything as true.
If u run the example you will get Output as : Jameel Moideen
Let’s understand why we need the three properties such as writable,enumerable and configurable.
writable
One of the very annoying part of the javascript is , if you change the toString property to something else for example
if you run this again , everything gets breaks. Let’s change writable to false. If run the same again you will get the correct output as ‘Jameel Moideen’ . This property will prevent overwrite this property later.
enumerable
if you print all the keys inside the object , you can see all the properties including toString.
console.log(Object.keys(employee));
if you set enumerable to false , you can hide toString property from everybody else. If run this again you will get firstName,lastName
configurable
if someone later redefined the object on later for example enumerable to true and run it. You can see toString property came again.
var employee = {
firstName: "Jameel",
lastName: "Moideen"
};
Object.defineProperty(employee, 'toString', {
value: function () {
return this.firstName + " " + this.lastName;
},
writable: false,
enumerable: false,
configurable: true
});
//change enumerable to false
Object.defineProperty(employee, 'toString', {
enumerable: true
});
employee.toString="changed";
console.log(Object.keys(employee));
you can restrict this behavior by set configurable to false.
Orginal reference of this information is from my personal Blog
yes no more function extending for setup setter & getter this is my example Object.defineProperty(obj,name,func)
var obj = {};
['data', 'name'].forEach(function(name) {
Object.defineProperty(obj, name, {
get : function() {
return 'setter & getter';
}
});
});
console.log(obj.data);
console.log(obj.name);
Source: Stackoverflow.com