Object.getOwnPropertyDescriptor & Object.defineProperty Methods.

 1) Property Descriptor:

When we create a JavaScript object, whether using object literal syntax or some other means and add some properties to it, each property (key) gets a default property descriptor. A property descriptor is a simple JavaScript object associated with each property of the object that contains information about that property such as its value and other meta-data.



2) Access Property Descriptor:


We need to use a static method provided by the Object. The Object.getOwnPropertyDescriptor method returns the property descriptor of the "prop" which is the property name on the "obj" object.


Object.getOwnPropertyDescriptor(obj, prop);


Own here means return the property descriptor of prop property only if that property belongs to the object obj and not on its prototype chain. If the property prop doesn’t exist on obj, it returns undefined.


The Object.getOwnPropertyDescriptor method returns an object with keys describing the setting and current value of the property. It returns the following:


1. The value property of the property descriptor is the current value of the property

2. writable is whether the user can assign a new value to the property

3. enumerable is whether this property will show up in enumerations like for in loop or for loop or Object.keys etc.

4. The configurable property tells whether the user has permission to change property descriptors such as to change the value of writable (not sure because in vs code even if the configurable is false, we are able to change the value of writable) and enumerable settings.



3)Modify Property Descriptor:


Object.defineProperty is used to create a new property on an object or update existing property with a custom descriptor.


When you define a new property on an object using Object.defineProperty and pass an empty {} descriptor, the default descriptor looks like below.

{

    value: undefined,

    writable: false,

    enumerable: false,

    configurable: false

}


Homework:

You can create or update multiple properties at once using Object.defineProperties which takes two arguments. First argument is target object on which properties have to be added/modified and second argument is object with key as property name and value as its property descriptor. This function returns the target object.

Basically the syntax is

Object.defineProperty(obj, prop, descriptor)

Where,

obj - The object on which to define the property.

prop -A string or Symbol specifying the key of the property to be defined or modified.

descriptor -

The descriptor for the property being defined or modified.


Using Object.getOwnPropertyDescriptor

let parentObj = {
propThree: 30,
}

let myObj = {
propOne: 10,
propTwo: 20,
__proto__: parentObj // Here we are making parentObj the prototype of myObj.
}

//get property descriptor of myObj
let descriptor = Object.getOwnPropertyDescriptor(myObj, "propOne");
console.log(descriptor); // All the values of the property descriptor are by default true.

descriptor = Object.getOwnPropertyDescriptor(myObj, "propThree");
console.log(descriptor); //Own in getOwnPropertyDescriptor means return the property descriptor of property only if that property belongs to the object and not on its prototype chain. If the property prop doesn’t exist on obj, it returns undefined. Here "propThree" property belongs to the prototype of myObj and not on myObj. Therefore undefined gets printed.










Using Object.defineProperty() to modify writable in the property descriptor of propOne property.

let parentObj = {
propThree: 30,
}

let myObj = {
propOne: 10,
propTwo: 20,
__proto__: parentObj // Here we are making parentObj the prototype of myObj.
}

//get property descriptor of myObj
let descriptor = Object.getOwnPropertyDescriptor(myObj, "propOne");
// console.log(descriptor);

descriptor = Object.getOwnPropertyDescriptor(myObj, "propThree");
// console.log(descriptor);


//When Writable property is true then only we can modify the value property of property
descriptor.
myObj.propOne = 50; // Here we are modifying the value of propOne from 10 to 50 and it will
be allowed since writable property in the property descriptor is true

console.log(myObj); // It will print myObj will the new value of propOne as 50.

//Modify Writable property to false by using Object.defineProperty() method.
Object.defineProperty(myObj, "propOne", { writable: false }); // Here we are Only modifying
the writable of propOne property no other properties writable will be modified.

myObj.propOne = 10; // Since the writable of propOne is set to false now, we can't modify the
value of propOne

console.log(myObj); // Hence myObj will get printed with the old value of propOne as 50 and
not 10.










Using Object.defineProperty() to add a new property propFour in myObj.

let parentObj = {
propThree: 30,
}

let myObj = {
propOne: 10,
propTwo: 20,
__proto__: parentObj // Here we are making parentObj the prototype of myObj.
}

//get property descriptor of myObj
let descriptor = Object.getOwnPropertyDescriptor(myObj, "propOne");
// console.log(descriptor);

descriptor = Object.getOwnPropertyDescriptor(myObj, "propThree");
// console.log(descriptor);


//When Writable property is true then only we can modify the value property of property
descriptor.
myObj.propOne = 50;
// console.log(myObj);

//Modify Writable property to false by using Object.defineProperty() method.
Object.defineProperty(myObj, "propOne", { writable: false });

myObj.propOne = 10;
// console.log(myObj);


//add new property
Object.defineProperty(myObj, "propFour", { value: 60, writable: true, enumerable: true,
configurable: false });
console.log(Object.getOwnPropertyDescriptor(myObj, "propFour")); // Here property descriptor
of propFour property will be displayed just like we have created.

myObj.propFour = 70; // Here we are changing the value of propFour from 60 to 70 and it will
be modified since we have given writable as true.
console.log(myObj); // So myObj with the new value of propFour will get printed

Object.defineProperty(myObj, "propFour", { enumerable: false });
console.log(Object.getOwnPropertyDescriptor(myObj, "propFour")); // this is givning an error.









Using Object.defineProperty to add a new property propFive and give it an empty {} property descriptor and also using Object.defineProperty to modify property descriptor of propTwo as empty{}


let parentObj = {
propThree: 30,
}

let myObj = {
propOne: 10,
propTwo: 20,
__proto__: parentObj // Here we are making parentObj the prototype of myObj.
}

//get property descriptor of myObj
let descriptor = Object.getOwnPropertyDescriptor(myObj, "propOne");
// console.log(descriptor);

descriptor = Object.getOwnPropertyDescriptor(myObj, "propThree");
// console.log(descriptor);


//When Writable property is true then only we can modify the value property of property
descriptor.
myObj.propOne = 50;
// console.log(myObj);

//Modify Writable property to false by using Object.defineProperty() method.
Object.defineProperty(myObj, "propOne", { writable: false });

myObj.propOne = 10;
// console.log(myObj);


//add new property
Object.defineProperty(myObj, "propFour", { value: 60, writable: true, enumerable: true,
configurable: false });
// console.log(Object.getOwnPropertyDescriptor(myObj, "propFour"));
myObj.propFour = 70;
// console.log(myObj);
/*Object.defineProperty(myObj, "propFour", { enumerable: false });
console.log(Object.getOwnPropertyDescriptor(myObj, "propFour")); */


// Giving Empty property descriptor
Object.defineProperty(myObj, "propFive", {});
console.log(Object.getOwnPropertyDescriptor(myObj, "propFive")); // we have created a new
property called propFive and given it an empty property descriptor so in it will get the
default values of property descriptors as shown in the console as propFive is a new property.

Object.defineProperty(myObj, "propTwo", {});
console.log(Object.getOwnPropertyDescriptor(myObj, "propTwo")); // Since propTwo was already
an existing property, even if we give it an empty property descriptor, its' previous property
descriptor will get printed in the console.













Using Object.defineProperty() to modify the enumerable of propTwo as false and then using Object.keys(myObj) to count the number of keys/properties left with myObj object.


let parentObj = {
propThree: 30,
}

let myObj = {
propOne: 10,
propTwo: 20,
__proto__: parentObj // Here we are making parentObj the prototype of myObj.
}

//get property descriptor of myObj
let descriptor = Object.getOwnPropertyDescriptor(myObj, "propOne");
// console.log(descriptor);

descriptor = Object.getOwnPropertyDescriptor(myObj, "propThree");
// console.log(descriptor);


//When Writable property is true then only we can modify the value property of property
descriptor.
myObj.propOne = 50;
// console.log(myObj);

//Modify Writable property to false by using Object.defineProperty() method.
Object.defineProperty(myObj, "propOne", { writable: false });

myObj.propOne = 10;
// console.log(myObj);


//add new property
Object.defineProperty(myObj, "propFour", { value: 60, writable: true, enumerable: true,
configurable: false });
// console.log(Object.getOwnPropertyDescriptor(myObj, "propFour"));
myObj.propFour = 70;
// console.log(myObj);
/*Object.defineProperty(myObj, "propFour", { enumerable: false });
console.log(Object.getOwnPropertyDescriptor(myObj, "propFour")); */


// Giving Empty property descriptor
Object.defineProperty(myObj, "propFive", {});
// console.log(Object.getOwnPropertyDescriptor(myObj, "propFive"));

Object.defineProperty(myObj, "propTwo", {});
// console.log(Object.getOwnPropertyDescriptor(myObj, "propTwo"));


//Modify Enumerable
Object.defineProperty(myObj, "propTwo", { enumerable: false });
console.log(Object.keys(myObj)); // Here we are using Object.keys method to count the number
of keys/properties of the object myObj, since we have modified the enumerable of propTwo as
false and propFive enumerable is also false by default because we passed empty property
descriptor, it will not be counted in the Object.keys. Hence the only properties/keys left
with myObj object is propOne and propFour and that is printed in the console.






Using Object.defineProperty() to add new propSix and making its' configurable and writable property descriptors as false and then consoling the result.
let parentObj = {
propThree: 30,
}

let myObj = {
propOne: 10,
propTwo: 20,
__proto__: parentObj // Here we are making parentObj the prototype of myObj.
}

//get property descriptor of myObj
let descriptor = Object.getOwnPropertyDescriptor(myObj, "propOne");
// console.log(descriptor);

descriptor = Object.getOwnPropertyDescriptor(myObj, "propThree");
// console.log(descriptor);


//When Writable property is true then only we can modify the value property of property descriptor.
myObj.propOne = 50;
// console.log(myObj);

//Modify Writable property to false by using Object.defineProperty() method.
Object.defineProperty(myObj, "propOne", { writable: false });

myObj.propOne = 10;
// console.log(myObj);


//add new property
Object.defineProperty(myObj, "propFour", { value: 60, writable: true, enumerable: true, configurable: false });
// console.log(Object.getOwnPropertyDescriptor(myObj, "propFour"));
myObj.propFour = 70;
// console.log(myObj);
/*Object.defineProperty(myObj, "propFour", { enumerable: false });
console.log(Object.getOwnPropertyDescriptor(myObj, "propFour")); */


// Giving Empty property descriptor
Object.defineProperty(myObj, "propFive", {});
// console.log(Object.getOwnPropertyDescriptor(myObj, "propFive"));

Object.defineProperty(myObj, "propTwo", {});
// console.log(Object.getOwnPropertyDescriptor(myObj, "propTwo"));


//Modify Enumerable
Object.defineProperty(myObj, "propTwo", { enumerable: false });
// console.log(Object.keys(myObj));

//Even if the configurable is false we are able to change the
value writable, like we did in the below example from 80 to 90
myObj.propSix = 80; // Here we are creating a new property propSix inside myObj object using
the dot (.) method.
Object.defineProperty(myObj, "propSix", { configurable: false }); // Here we are setting the
configurable of propSix as false
console.log(myObj);

myObj.propSix = 90;
console.log(myObj); // Even after configurable was false, we could change the value of writable
from 80 to 90

Object.defineProperty(myObj, "propSix", { writable: false }); // We are setting writable false
here.
myObj.propSix = 100;
console.log(myObj); // since the writable of propSix was set as false, now propSix will not
get updated to 100 and will remain at its' previous value 90 only.








4) 
Ways of creating an Object Literal with prototype assignment
//custom prototype during object creation
let obj = Object.create(Object.prototype = {
a: { value: 1, writable: false },
b: { value: 2, writable: true }
});
console.log(obj.__proto__);


//assigning existing prototype during object creation
let animal = {
legs: 4,
}
let dog = Object.create(animal, { sound: { value: 'Bark' } });
let descriptor = Object.getOwnPropertyDescriptor(dog, "sound");
console.log(descriptor);


// This code will produce the same result as the above code and is use more often in the
developer world
/*
let dog = {
sound: 'Bark',
__proto__: animal
}*/
// console.log(dog.legs);//4
// console.log(Object.getPrototypeOf(dog));//animal
// console.log(Object.getPrototypeOf(animal));//JS Object










5)Multilevel Inheritance


Multi-level inheritance can be defined as an inheritance in which a child class inherits the properties from another child class, which inherited from the parent class and so on. 

The multi-level inheritance has multiple base classes.


Class A 

   |

Class B 

   |

Class C 


class Animal {
eat() {
console.log("eating");
}
}
class Lion extends Animal {
roar() {
console.log("roaring");
}
}
class BabyLion extends Lion {
// roar() {
// console.log("BabyLion roaring");
// }
weep() {
console.log("weeping");
}
}
let obj = new BabyLion();
obj.eat();
obj.roar();
obj.weep();












6) Primitive Data Types

JavaScript has only primitive types, null, undefined, and objects. 


In JavaScript, there are six primitive data types:


  1. Boolean: A boolean value represents a logical entity and can have two values, either true or false.

  2. Null: The value null represents the intentional absence of any object value.

  3. Undefined: The value undefined is assigned to a variable that is not assigned a value.

  4. Number: A number data type represents numeric values. It can be any integer or floating-point value.

  5. String: A string is a sequence of characters that represent text. It is enclosed in single or double quotes.

  6. Symbol: A symbol is a unique and immutable value that may be used as the key of an Object property.


In JavaScript:


  • Object is a non-primitive data type that represents a collection of key-value pairs. It can contain properties and methods that can be accessed using dot notation or square bracket notation. Objects can be created using object literals, constructor functions, or the Object.create() method.

  • null is a primitive value that represents the intentional absence of any object value. It is often used to signify a missing or non-existent value. When a variable is set to null, it means that it has no value or it does not refer to any object.

  • undefined is a primitive value that represents an uninitialised, non-existent, or undefined value. When a variable is declared but not assigned a value, it is automatically assigned the value of undefined.


Note that null and undefined are distinct values in JavaScript. null is an explicitly assigned value that represents the absence of any object value, while undefined is a default value that is assigned to a variable that is not initialised or does not have a value.



Comments

Popular posts from this blog

Scope and Closures / Callback Hell

DOM - Document Object Model (document.getElementById etc.)