Fading Coder

One Final Commit for the Last Sprint

Home > Tech > Content

JavaScript Object-Oriented Programming Fundamentals: Prototypes, Constructors, and This Binding

Tech May 11 2

Object-Oriented Concepts

Understanding Objects

Objects represent real-world entities in programming:

  • They serve as containers encapsulating properties and methods
  • They aggregate data collections and functional sets
  • They form unordered property collections

Object-Oriented Programming

This paradigm abstracts complex real-world relationships into individual objects, enabling simulation through object collaboration.

Core OOP Principles

Encapsulation, inheritance, and polymorphism form the foundation of object-oriented design.

Object Creation Patterns

Literal Notation

const textbook = {
  cost: 30,
  title: "JavaScript",
  educate: function() {
    console.log(this.title + " imparts knowledge")
  }
}
console.log(textbook.cost) // 30
textbook.educate() // JavaScript imparts knowledge

Constructor Pattern with new

const vehicle = new Object()
vehicle.model = "BYD"
vehicle.park = function() {
  console.log(this.model + ' can park!')
}
console.log(vehicle) // {model: 'BYD', park: ƒ}
vehicle.park() // BYD can park!

Factory Pattern

const buildVehicle = function (color, model, parkingFunc) {
  const veh = new Object()
  veh.color = color
  veh.model = model
  veh.park = parkingFunc
  return veh // Must return the object
}
const v1 = buildVehicle("black", "Audi", function () {
  console.log(this.model + " can park downstairs")
})
console.log(v1) // {model: 'Audi', color: 'black', park: ƒ}
v1.park() // Audi can park downstairs

Constructor Functions

function Human(name, years) {
  this.name = name
  this.years = years
  this.learn = function() {
    console.log(this.name + " enjoys learning")
  }
}
const person1 = new Human("Xiaohua", 10)
console.log(person1) // Human {name: 'Xiaohua', years: 10, learn: ƒ}
person1.learn() // Xiaohua enjoys learning

Constructor-Instance Relationships

Instance Creation Proceess

Constructor functions create new instances through the new operator:

  • Creates a fresh object
  • Sets this context to the new object
  • Executes constructor code
  • Returns the new object
const Vessel = function (manufacturer) {
  this.manufacturer = manufacturer
}
const glass = new Vessel("Lucky")
console.log(glass) // Vessel {manufacturer: 'Lucky'}
console.log(glass.constructor)

Constructor Property

Every object possesses a constructor property pointing back to its creating function.

JavaScript includes various object types: custom objects, DOM elements, BOM components, and built-in objects.

// Custom object
const auto = new Object()
console.log(auto.constructor) // ƒ Object() { [native code] }

// DOM element
const paragraph = document.getElementById('text')
console.log(paragraph.constructor) // ƒ HTMLParagraphElement()

// Browser history
console.log(window.history.constructor) // ƒ History() { [native code] }

// Date object
console.log(new Date().constructor) // ƒ Date()

// Function object
function sample() {}
console.log(sample.constructor) // ƒ Function() { [native code] }

Object Type Detection

Instanceof Operator

The instanceof operator determines if a value is an object instance:

const vehicleObj = {}
const numberArray = []
const callback = function () {}

console.log(vehicleObj instanceof Object) // true
console.log(numberArray instanceof Object) // true
console.log(callback instanceof Object) // true
console.log(12.4 instanceof Object) // false
console.log('23.4' instanceof Object) // false

Memory Managemnet in Constructors

Memory Lifecycle

Memory management involves three phases:

  1. Allocation during variable declaration or function creation
  2. Usage during operations and method calls
  3. Deallocation through JavaScript's automatic garbage collection

Addressing Memory Inefficiency

Global Property Sharing

// Shared resources
const commonAge = 18
const sharedLearning = function () {
  console.log(this.identifier + ' enjoys studying JS')
}

function Individual(identifier, age, gender, learningFunc) {
  this.identifier = identifier
  this.age = age
  this.gender = gender
  this.study = learningFunc
}

const ind1 = new Individual('Xiaohua', commonAge, 'female', sharedLearning)
const ind2 = new Individual('Xiaoming', commonAge, 'male', sharedLearning)

console.log(ind1) // Individual {identifier: 'Xiaohua', age: 18, gender: 'female', study: ƒ}
console.log(ind2) // Individual {identifier: 'Xiaoming', age: 18, gender: 'male', study: ƒ}
ind1.study() // Xiaohua enjoys studying JS
ind2.study() // Xiaoming enjoys studying JS

Prototype-Based Solutions

Prototypes provide two key benefits:

  1. Memory space optimization
  2. Data sharing capabilities

Prototype Relationships

Function Prototypes

All functions possess a prototype property, which is a object itself:

function sampleFunction() {}
console.log(sampleFunction.prototype instanceof Object) // true
console.log(typeof sampleFunction.prototype) // object

Constructor Prototypes

function Automobile(model) {
  this.model = model
}
Automobile.prototype.hue = "white"
Automobile.prototype.playAudio = function () {
  console.log("can play music")
}
const auto1 = new Automobile('BYD')
console.log(Automobile.prototype)
console.log(auto1.hue) // white

Prototype Chain Properties

  • Instance objects have constructor properties pointing to their constructors
  • Prototype objects also have constructor properties pointing to constructors
  • All objects have __proto__ properties linking to their constructor's prototype
const Container = function (maker) {
  this.maker = maker
}
const container = new Container("bbb")
console.log(container.constructor)
console.log(Container.prototype.constructor === Container) // true
console.log(container.__proto__ === Container.prototype) // true

Prototype Chains

Chain Resolution

When accessing object properties, JavaScript traverses the prototype chain:

  • First checks the object itself
  • Then searches up the __proto__ chain
  • Eventually reaches null at the end

Property Lookup Rule

The search order follows: instance → prototype chain → undefined

function Sample() { }
Sample.prototype.value = 1

const instanceB = new Sample()

Sample.prototype = {
    value: 2,
    metric: 3
}
const instanceC = new Sample()

console.log(instanceB.value) // 1
console.log(instanceB.metric) // undefined
console.log(instanceC.value) // 2
console.log(instanceC.metric) // 3

Prototype Chain Structure

function Bottle(brand, volume) {
  this.brand = brand
  this.volume = volume
}
const bottle = new Bottle('Monqing', '200ml')
console.log(bottle.volume) // 200ml
console.log(bottle.__proto__ === Bottle.prototype) // true

// Prototype objects also have __proto__ pointing to Object.prototype
console.log(Bottle.prototype.__proto__ === Object.prototype) // true

// Object.prototype's __proto__ points to null
console.log(Object.prototype.__proto__) // null

Context Binding Methods

Common Characteristics

These methods share similar functionality for context manipulation.

Call Method

const personName = 'Xiaohua'
function greet() {
  console.log('I am a function')
}
greet() // I am a function
greet.call() // I am a function

const personA = {
  personName: 'Xiaoming',
  fetchName: function () {
    console.log(this.personName)
  }
}
personA.fetchName.call() // Xiaohua (when no argument, context is window)

const personB = {
  personName: 'Xiaogang',
  fetchName: function () {
    console.log(this.personName)
  }
}
personA.fetchName.call(personB) // Xiaogang

Apply Method

Similar to call() but accepts arguments as an array:

console.log(Math.max(30, 40, 50)) // 50
console.log(Math.max.apply(null, [30, 40, 50])) // 50
console.log(Math.max.apply(window, [30, 40, 50])) // 50

Bind Method

Creates a new function with bound context without immediate execution:

const studentName = "Xiaohua"
const boundFunction = function fn() {
  console.log(this.studentName)
}.bind()
boundFunction() // Xiaohua

const studentB = {
  studentName: 'Xiaogang',
  getName: function () {
    console.log(this.studentName)
  }
}

const studentC = {
  studentName: 'Xiaoli',
  getName: function () {
    console.log(this.studentName)
  }.bind(studentB) // Xiaogang
}

This Context in Functions

When instances invoke methods, this refers to the instance. When prototype methods are called, this refers to the prototype context.

function Glass(name) {
  this.name = name
  this.use = function () {
    console.log(this.name + " can be used for drinking")
  }
}
Glass.prototype.name = "I am prototype"

const glass = new Glass("Xiaomi Glass")
glass.use() // this refers to Xiaomi Glass
console.log(Glass.prototype.name) // outputs I am prototype
Tags: javascript

Related Articles

Understanding Strong and Weak References in Java

Strong References Strong reference are the most prevalent type of object referencing in Java. When an object has a strong reference pointing to it, the garbage collector will not reclaim its memory. F...

Comprehensive Guide to SSTI Explained with Payload Bypass Techniques

Introduction Server-Side Template Injection (SSTI) is a vulnerability in web applications where user input is improper handled within the template engine and executed on the server. This exploit can r...

Implement Image Upload Functionality for Django Integrated TinyMCE Editor

Django’s Admin panel is highly user-friendly, and pairing it with TinyMCE, an effective rich text editor, simplifies content management significantly. Combining the two is particular useful for bloggi...

Leave a Comment

Anonymous

◎Feel free to join the discussion and share your thoughts.