ReasonJun

javascript : Prototype (1) (concept, object.freeze/seal/preventExtension) 본문

Frontend/Javasciprt

javascript : Prototype (1) (concept, object.freeze/seal/preventExtension)

ReasonJun 2023. 6. 7. 02:16
728x90

In JavaScript, the prototype is an internal property of objects that allows objects to inherit properties and methods from other objects. Every JavaScript object has a prototype, except for the base object Object.prototype, which is the ultimate prototype for all objects.

 

The prototype forms the basis for JavaScript's prototype-based inheritance model. When you access a property or method on an object, JavaScript first checks if the object itself has that property or method. If not, it looks up the prototype chain to find the property or method in the prototype of the object.

Here's how prototypes work:

  1. Constructor Functions: In JavaScript, you can create objects using constructor functions. Constructor functions act as blueprints to create multiple objects with similar properties and methods. When you create an object using a constructor function, the prototype property of the constructor function is automatically assigned as the prototype of the created object.

Example:

function Person(name) {
  this.name = name;
}

Person.prototype.sayHello = function() {
  console.log(`Hello, my name is ${this.name}`);
};

const john = new Person('John');
john.sayHello(); // Output: Hello, my name is John

In this example, the Person function serves as a constructor function for creating Person objects. The sayHello method is added to the Person.prototype, and all Person objects created using the constructor function inherit this method.

  1. Object.prototype: Object.prototype is the default prototype for all objects in JavaScript. It provides a set of common methods and properties that are available to all objects. These include methods like toString(), valueOf(), and properties like hasOwnProperty().

Example:

const obj = {};

console.log(obj.toString()); // Output: [object Object]
console.log(obj.hasOwnProperty('toString')); // Output: false

In this example, the obj object inherits the toString() method from Object.prototype, which provides a default string representation of the object.

  1. Prototype Chain: Objects can inherit properties and methods from their prototype, forming a prototype chain. When you access a property or method on an object, JavaScript checks the object itself, and if it doesn't find the property or method, it looks up the prototype chain until it finds the property or reaches the end of the chain.

Example:

function Person(name) {
  this.name = name;
}

Person.prototype.sayHello = function() {
  console.log(`Hello, my name is ${this.name}`);
};

function Student(name, grade) {
  Person.call(this, name);
  this.grade = grade;
}

Student.prototype = Object.create(Person.prototype);
Student.prototype.constructor = Student;

const alice = new Student('Alice', 9);
alice.sayHello(); // Output: Hello, my name is Alice

In this example, the Student object inherits the sayHello() method from the Person prototype, which is further up in the prototype chain.

 

Understanding prototypes is essential for working with objects in JavaScript. Prototypes allow you to share functionality between objects, enable inheritance, and provide a mechanism for extending and modifying existing objects. They are a fundamental aspect of JavaScript's object-oriented programming capabilities.

 

// const fruits = ['apple', 'banana', 'cherry']

const fruits = new Array('apple', 'banana', 'cherry');

console.log(fruits); // [ 'apple', 'banana', 'cherry' ]
console.log(fruits.length); // 3
console.log(fruits.includes('banana')); // true

Array.prototype.you = function () {
  console.log(this);
};

fruits.you(); // [ 'apple', 'banana', 'cherry' ]

const arr = [];
arr.you(); // []

// const youjun = {
//   firstName: 'you',
//   lastName: 'jun',
//   getFullName: function () {
//     return `${this.firstName} ${this.lastName}`;
//   },
// };

// const neo = {
//   firstName: 'Neo',
//   lastName: 'Anderson',
// };

// console.log(youjun.getFullName()); // you jun
// console.log(youjun.getFullName.call(neo)); // Neo Anderson

// The first letter must be uppercase.
function User(first, last) {
  this.firstName = first;
  this.lastName = last;
}

// Arrow functions should not be used.
User.prototype.getFullName = function () {
  return `${this.firstName} ${this.lastName}`;
};

const heropy = new User('Heropy', 'Park');

console.log(heropy); // User { firstName: 'Heropy', lastName: 'Park' }
console.log(heropy.getFullName()); // Heropy Park
const dog = { name: '와우', emoji: '🐶' };

console.log(Object.keys(dog)); //[ 'name', 'emoji' ]
console.log(Object.values(dog)); // [ '와우', '🐶' ]
console.log(Object.entries(dog)); // [ [ 'name', '와우' ], [ 'emoji', '🐶' ] ]

console.log('name' in dog); // true
console.log(dog.hasOwnProperty('name')); // true

// Each property of an object is stored in an object called a property descriptor.
const descriptors = Object.getOwnPropertyDescriptors(dog);
console.log(descriptors);
/*
{
  name: { value: '와우', writable: true, enumerable: true, configurable: true },
  emoji: { value: '🐶', writable: true, enumerable: true, configurable: true }
} 
*/

const desc = Object.getOwnPropertyDescriptor(dog, 'name');
console.log(desc);
/*
{ value: '와우', writable: true, enumerable: true, configurable: true }
*/

Object.defineProperty(dog, 'name', {
  value: '멍멍',
  writable: false,
  enumerable: false,
  configurable: false,
});

console.log(dog.name); // 멍멍
console.log(Object.keys(dog)); // [ 'emoji' ]
delete dog.name;
console.log(dog.name); // 멍멍

const student = {};
Object.defineProperties(student, {
  firstName: {
    value: 'youjun',
    writable: true,
    enumerable: true,
    configurable: true,
  },
  lastName: {
    value: 'lee',
    writable: true,
    enumerable: true,
    configurable: true,
  },
  fullName: {
    get() {
      return `${this.lastName} ${this.firstName}`;
    },
    set(name) {
      [this.lastName, this.firstName] = name.split(' ');
    },
    configurable: true,
  },
});
console.log(student); // { firstName: 'youjun', lastName: 'lee' }
console.log(student.fullName); // lee youjun

object.freeze

  1. Property Modification: Attempts to modify existing properties or add new properties to the frozen object are ignored. In strict mode, such modifications will throw an error, while in non-strict mode, they silently fail.
  2. Value Modification: Existing property values cannot be changed. Assigning a new value to a property of a frozen object will have no effect.
  3. Property Deletion: Properties cannot be deleted from a frozen object. Attempts to use the delete operator on properties of a frozen object will be ignored or throw an error in strict mode.
const youjun = { name: 'youjun' };

const obj = {
  prop1: 'value1',
  prop2: 'value2',
  owner: { name: 'youjun' }
};

Object.freeze(obj); // but shallow 

obj.prop1 = 'new value'; // Ignored, no effect
obj.prop3 = 'value3'; // Ignored, no effect
delete obj.prop2; // Ignored, no effect

console.log(obj.prop1); // Output: value1
console.log(obj.prop2); // Output: value2
console.log(obj.prop3); // Output: undefined

youjun.name = 'neo';
console.log(obj); // { name: 'neo' }

object.seal

  1. Property Addition and Deletion: Attempts to add new properties or delete existing properties from the sealed object are ignored. In strict mode, such operations will throw an error, while in non-strict mode, they silently fail.
  2. Property Modification: Existing property values can be modified. Assigning a new value to an existing property of a sealed object is allowed.
const obj = {
  prop1: 'value1',
  prop2: 'value2'
};

Object.seal(obj);

obj.prop1 = 'new value'; // Allowed, property value is modified
obj.prop3 = 'value3'; // Ignored, no effect
delete obj.prop2; // Ignored, no effect

console.log(obj.prop1); // Output: new value
console.log(obj.prop2); // Output: value2
console.log(obj.prop3); // Output: undefined

object.preventExtension

  1. Property Addition: Attempts to add new properties to the non-extensible object are ignored. In strict mode, such additions will throw an error, while in non-strict mode, they silently fail.
  2. Property Modification: Existing property values can be modified.
  3. Property Deletion: Existing properties can be deleted.
const obj = {
  prop1: 'value1',
  prop2: 'value2'
};

Object.preventExtensions(obj);

obj.prop1 = 'new value'; // Allowed, property value is modified
obj.prop3 = 'value3'; // Ignored, no effect
delete obj.prop2; // Allowed, property is deleted

console.log(obj.prop1); // Output: new value
console.log(obj.prop2); // Output: undefined
console.log(obj.prop3); // Output: undefined
728x90
Comments