首页  >  文章  >  web前端  >  JS 中的面向对象编程

JS 中的面向对象编程

PHPz
PHPz原创
2024-08-29 13:39:211109浏览

OOP in JS

范式是指代码的风格及其组织方式。常见的编程范式有:OOP、函数式等。要成为一名开发人员,您需要很好地了解 OOP。

面向对象编程

  • 最流行的企业编程范例。
  • 基于对象
  • 以组织代码为目标而开发
  • 使代码更加灵活、可维护。
  • 在 OOP 之前,代码分散在全局范围内的多个 fns 中,没有任何结构。这种风格被称为意大利面条代码,很难维护,忘记添加新功能。
  • 用于通过代码创建对象。
  • 还可以实现对象之间的交互。

API

  • 对象外部的代码可以访问并用于与其他对象通信的方法。

班级

  • 用于创建对象的抽象蓝图。
  • 从类实例化,即使用类蓝图创建。
  • 使用“new Class()”语法从一个类创建多个对象

课程设计:

  • 使用 OOP 的 4 个原则完成,即抽象、封装、继承、多态
  • 抽象:隐藏对最终用户来说无关紧要的不必要的细节。
  • 封装:将一些属性方法保持为私有,这使得它们只能从类内部访问,并且无法从类外部访问。公开一些方法作为与外部世界交互的公共接口 API。因此,它可以防止外部代码操纵内部状态[对象的数据],因为这可能是错误的重要来源。公共接口是非私有的代码。将方法设为私有使我们可以更轻松地更改代码的实现,而不会破坏外部依赖关系。总结:很好地封装状态和方法,只公开必要的方法。
  • 继承:重复的代码很难维护。因此,这个概念通过继承已经编写的代码来支持代码的可重用性。子类通过继承父类的所有属性和方法来扩展父类。此外,子类实现了自己的数据功能以及继承的功能。
  • 多态性:子类可以覆盖从父类继承的方法。

对象是:

  • 用于对现实世界或抽象特征进行建模。
  • 可能包含数据(属性)和代码(方法)。帮助我们将数据和代码打包在一个块中
  • 独立的代码片段/块。
  • appln的构建块,相互交互。
  • 黑白对象的交互通过公共接口API发生。
  • 从类创建的所有对象都称为该类的实例。
  • 所有对象都可以包含不同的数据,但它们都共享共同的功能

经典传承:

  • 支持Java、C++、Python等
  • 一个类继承另一个类
  • 方法或行为从类复制到所有实例。

JS 中的委托或原型继承:

  • 像古典语言一样支持所有 OOP 原则。
  • 从类继承的实例。
  • 原型包含所有链接到该原型的对象都可以访问的方法。 原型:包含方法 object:可以访问原型的方法,使用proto链接连接到原型对象。
  • 对象继承原型对象上定义的属性和方法。
  • 对象将行为委托给原型对象。
  • 用户定义的数组实例通过 proto 链接访问 Array.prototype.map() 上的 .map(),即原型对象上定义的 map()。因此,.map() 不是在我们的实例上定义的,而是在原型上定义的。
## 3 Ways to implement Prototypal Inheritance via:
1. Constructor Fn:
- To create objects via function.
- Only difference from normal fn is that they are called with 'new' operator.
- Convention: always start with a capital letter to denote constructor fn. Even builtins like Array, Map also follow this convention.
- An arrow function doesn't work as Fn constructor as an arrow fn doesn
t have its own 'this' keyword which we need with constructor functions.
- Produces an object. 
- Ex. this is how built-in objects like Array, Maps, Sets are implemented

2. ES6 Classes:
- Modern way, as compared to above method.
- Syntactic sugar, although under the hood work the same as above syntax.
- ES6 classes doesn't work like classical OOP classes.

3. Object.create()
- Way to link an object to its prototype
- Used rarely due to additional repetitive work.

## What does 'new' operator automates behind the scene?
1. Create an empty object {} and set 'this' to point to this object.
2. Create a __proto__ property linking the object to its parent's prototype object.
3. Implicit return is added, i.e automatically return 'this {} object' from the constructor fn.

- JS doesn't have classes like classical OOP, but it does create objects from constructor fn. Constructor fn have been used since inception to simulate class like behavior in JS.
Ex. validate if an object is instance of a constructor fn using "instanceOf" operator.

const Person = function(fName, bYear) {
  // Instance properties as they will be available on all instances created using this constructor fn.
  this.fName = fName;
  this.bYear = bYear;

  // BAD PRACTICE: NEVER CREATE A METHOD INSIDE A CONSTRUCTOR FN.
  this.calcAge = function(){
console.log(2024 - this.bYear);
}
};

const mike = new Person('Mike', 1950);
const mona = new Person('Mona', 1960);
const baba = "dog";

mike; // Person { fName: 'Mike', bYear: 1950 }
mona; // Person { fName: 'Mona', bYear: 1960 }

mike instanceof Person; // true
baba instanceof Person; // true


If there are 1000+ objects, each will carry its own copy of fn defn.
Its a bad practice to create a fn inside a contructor fn as it would impact performance of our code.

原型对象:

  • 每个函数,包括JS中的构造函数fn,都有一个名为prototype对象的属性。
  • 从此构造函数 fn 创建的每个对象都可以访问构造函数 fn 的原型对象。前任。 Person.prototype
  • 通过以下方式将 fn 添加到此原型对象: Person.prototype.calcAge = function(bYear){ console.log(2024 年 - bYear); };

mike.calcAge(1970); // 54
莫娜.calcAge(1940); // 84

  • mike 对象不会包含 .calcAge(),但它将使用 Person.prototype 对象上定义的 proto 链接来访问它。
  • 'this' 始终设置为调用该函数的对象。

迈克。原型; // { calcAge: [函数(匿名)] }
莫娜。原型; // { calcAge: [函数(匿名)] }

迈克。原型 === Person.prototype; // true

  • Person.prototype here serves as prototype for all the objects, not just this single object created using Person constructor fn.

Person.prototype.isPrototypeOf(mike); // true
Person.prototype.isPrototypeOf(Person); // false

  • prototype should have been better named as prototypeOfLinkedObjects generated using the Constructor fn.
  • Not just methods, we can create properties also on prototype object. Ex. Person.prototype.creatureType = "Human"; mike.creatureType; // Human mona.creatureType; // Human

Different properties for an object:

  • Own property and properties on constructor fn accessbile via proto link of objects.
  • To check own property for objects, use:
    mike.hasOwnProperty('fName'); // true
    mona.hasOwnProperty('creatureType'); // false

  • Two way linkage:
    Person() - constructor fn
    Person.prototype - Prototype

Person() constructor fn links to Person.prototype via .prototype
Person.prototype prototype links back to Person() constructor fn via .constructor to Person() itself.

proto : always points to Object's prototype for all objects in JS.
newly created object is automatically returned, unless we explicitly return something else and stored in the LHS variable declared.

Prototype Chain:

  • Similar to scope chain. Look for variable in the scope level
  • Prototype chain has to lookup for finding properties or methods.
  • All objects in JS has a proto link Person Person.proto Person.proto.proto; // [Object: null prototype] {}

Top Level Object in JS:
Object() - constructor fn
Object.prototype - Prototype
Object.prototype.proto // null

Object.prototype methods:

  • constructor: f Object()
  • hasOwnProperty
  • isPrototypeOf
  • propertyIsEnumerable
  • toLocaleString
  • toString
  • valueOf
  • defineGetter etc

// Takes to constructor fn prototype
mike.proto === Person.prototype; // true
// Takes to parent of constructor fn's prototype i.e Object fn
mike.proto.proto; // [Object: null prototype] {}
// Takes to parent of Object fn i.e end of prototype chain
mike.proto.proto.proto; // null

  • All fns in JS are objects, hence they also have a prototype
  • console.dir(x => x+1);
  • Fns are objects, and objects have prototypes. So a fn prototype has methods which can be called.
  • const arr = [2,4,21]; // is same as using 'new Array' syntax
    arr.proto; // shows fns on array's prototype

  • Each array doesn't have all of these methods, its able to use it via proto link.

  • arr.proto === Array.prototype; // true

const arr = [2,4,21];
arr.proto; // Array prototype
arr.proto.proto; // Object prototype
arr.proto.proto.proto; // null

## If we add a fn to Array.prototype, then all newly created arrays will inherit that method. However extending the prototype of a built-in object is not a good idea. Incase new version of JS adds a method with the same name, will break your code. Or in case multiple Devs create similar fnality with different names will add an unnecessary overhead.
Ex. Add a method named unique to get unique values
const arr = [4,2,4,1,2,7,4,7,3];
Array.prototype.uniq = function(){
return [...new Set(this)];
}
arr.uniq(); // [ 4, 2, 1, 7, 3 ]
  • All DOM elements behind the scene are objects.
  • console.dir(h1) // will show you it in object form
  • Prototype chain: h1 -> HTMLHeadingElement -> HTMLElement -> Element -> Node -> EventTarget -> Object

以上是JS 中的面向对象编程的详细内容。更多信息请关注PHP中文网其他相关文章!

声明:
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn