20

代码详解:使用JavaScript进行面向对象编程的指南

 4 years ago
source link: http://developer.51cto.com/art/201911/606172.htm
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

一切都从对象开始。

f2aEnua.jpg!web

对象,即我们相互交流的一个载体,有其属性和方法。对象是面向对象编程的核心,不仅用于JavaScript,而且还适用于Java、C语言、C++等。不再考虑单个变量和函数,而选择自给型的对象。

以下是在讨论面向对象编程(OOP)时最常用到的概念:

  • 对象,属性,方法
  • 封装
  • 抽象
  • 复用/继承
  • 多态性
  • 关联
  • 聚合
  • 组合

1. 对象,属性,方法

1.1 对象字面量(Objectliteral)

在大括号中设置属性,从而在JavaScript中创建一个新对象。对象字面量属性值可以是任何数据类型,如函数字面量、数组、字符串、数字或布尔值。

下面创建一个命名图书的对象,其属性包括作者、出版年份、标题和方法。

— summary. 
 
constbook = { 
title: "Hippie", 
author: "Paulo Coelho", 
year: "2018" 
} 

对象创建完成后,可以使用点记法获取值。例如,可以使用book.title.获取标题的值,还可以使用方括号book[‘title’]访问属性。

1.2 对象构造函数(Objectconstructor)

对象构造函数与常规函数相同。每次创建对象时都会用到。可将其与新关键字一起使用。当需要创建具有相同属性和方法的多个对象时,对象构造函数非常有用。

constbook = { 
 
title: "Hippie", 
 
author: "Paulo Coelho", 
 
year: "2018" 
 
}const book1 = { 
 
title: "The Alchemist", 
 
author: "Paulo Coelho", 
 
year: "1988", 
 
} 

如果要创建多个书籍(book)对象,必须为每本书复制代码。可以继续创建 book对象,但这有点麻烦——不过对象构造函数有助于再次使用对象字面量。

functionBook(title, author, year) { 
 
this.title = title; 
 
this.author = author; 
 
this.year = year; 
 
}const book1 = new Book ('Hippie', 'Paulo Coelho', 
 
'2018'); 
 
console.log(book1); 
 
> Book { 
 
title: "Hippie", 
 
author: "Paulo Coelho", 
 
year: "2018" 
 
}// if we want to create more than onebook just we call 
 
function book with new keyword.const book2 
 
= new Book ('TheAlchemist', 'Paulo Coelho', '1988'); 

book1 和 book2创建 Book的实例并将其分配给变量。想知道一个对象是否是另一个对象的实例。可以用instanceof。

book1 instanceof Book 
 
> true 

1.3 Object.create()方法

JavaScript中的每个对象都将从主对象创建。任何时候使用大写字母“O”时,指的都是主对象。我们可以在console控制台中打印主对象。主对象有很多方法,下面来看object.create()方法。

7R3QFbu.jpg!web

Object.create()创建法使用现有对象作为原型来创建新对象。基本语法如下:

Object.create(proto,[propertiesObject]) 

proto是新建对象的原型。 propertiesObject是一个可选项。

下面举个简单的例子:

constBook = { 
 
summary : function() { 
 
console.log(`${this.title} iswritten by ${this.author}.`) 
 
} 
 
}const book1 = Object.create(Book); 
 
book1.author = "Paulo Coelho"; 
 
book1.title = "Hippie";console.log(book1.summary()); 
 
> Hippie is written by Paulo Coelho. 

以上的例子创建了一个原始对象book1,并为作者和标题赋值。可以看到原始对象中的汇总函数:

iUF7zyr.jpg!web

下面将Object.create() 方法进行详细介绍。

2. 类

类不是对象,它是对象的蓝本,是特殊函数。可以使用函数的表达式和声明来定义函数,也可以这样定义类。蓝本可用来表示对象的数量。

可以使用类的关键字和名称。语法与Java相似。

类语法是使用面向对象编程和管理原型的一个好途径:

let Book= function(name) { 
 
this.name = name 
 
}let newBook = function(name) { 
 
Book.call(this, name) 
 
} newBook.prototype = Object.create(Book.prototype); 
 
const book1 = new newBook("The Alchemist"); 

此例使用了ES6类语法:

classBook { 
 
constructor(name) { 
 
this.name = name 
 
} 
 
}class newBook extends Book { 
 
constructor(name) { 
 
super(name); 
 
} 
 
}const book1 = new newBook("The Alchemist"); 

类语法是语法糖(syntactical sugar)—而场景背后它仍然使用基于原型的模型。类是函数,而函数是JavaScript中的对象。

classBook { 
 
constructor(title, author){ 
 
this.title = title; 
 
this.author = author; 
 
} 
 
summary() { 
 
console.log(`${this.title} writtenby ${this.author}`); 
 
} 
 
}const book1 = new Book("", ""); 
 
console.log(typeof Book); 
 
> "function"console.log(typeof book1); 
 
> "object" 

3. 封装(Encapsulation)

封装意为隐藏信息或数据。指对象在不向外部使用者透露任何执行细节的情况下执行其功能。换句话说,就是其私有变量只对当前函数可见,而对全局范围或其他函数不可访问。

constBook = function(t, a) { 
 
let title = t; 
 
let author = a; 
 
return { 
 
summary : function() { 
 
console.log(`${title} written by${author}.`); 
 
} 
 
} 
 
} 
 
const book1 = new Book('Hippie', 'Paulo Coelho'); 
 
book1.summary(); 
 
> Hippie written by Paulo Coelho. 

在上面的代码中,标题和作者只在函数Book 的范围内可见,方法summary对Book的使用者可见。所以书名和作者被封装在Book中。

4. 抽象

抽象意为实现隐藏。它是一种隐藏实现细节的方法,只向使用者显示基本特性。换句话说,它隐藏了不相关的细节,只显示了必须对外部世界显示的。缺乏抽象会导致代码出现可维护性问题。

constBook = function(getTitle, getAuthor) { 
 
// Private variables / properties 
 
let title = getTitle; 
 
let author = getAuthor;// Publicmethod 
 
this.giveTitle = function() { 
 
return title; 
 
} 
 
// Private method 
 
const summary = function() { 
 
return `${title} written by${author}.` 
 
}// Public method that has access toprivate method. 
 
this.giveSummary = function() { 
 
return summary() 
 
} 
 
}const book1 = new Book('Hippie', 'Paulo Coelho'); 
 
book1.giveTitle(); 
 
> "Hippie"book1.summary(); 
 
> Uncaught TypeError: book1.summary is not a 
 
functionbook1.giveSummary(); 
 
> "Hippie written by Paulo Coelho." 

5. 复用/继承

JavaScript继承是一种机制,允许我们使用现有的类创建一个新类。也就是子类继承父类的所有属性和行为。

一般来说,JavaScript不是一种基于类的语言。关键字“类”是在ES6中引入的,但它是语法糖,JavaScript仍然是基于原型的。在JavaScript中,继承是通过使用原型来实现的。这种模式称为行为委托模式或原型继承。

同样可以通过book例子来体现:

functionBook(title, author, year) { 
 
this.title = title; 
 
this.author = author; 
 
this.year = year; 
 
this.summary = function() { 
 
console.log(`${this.title} iswritten by ${this.author}.`) 
 
} 
 
} 
 
const book1 = new Book ('Hippie', 'Paulo Coelho', '2018'); 
 
const book2 = newBook ('The Alchemist', 'Paulo Coelho', 
 
'1988'); 

原型继承

对于Book的每个实例,我们都在为基类中的方法重建内存。这些方法必须在所有实例之间共享 — 不应特定于个别实例中。图中的原型是:

letCorebook = function(title) { 
 
this.title = title 
 
}Corebook.prototype.title = function() { 
 
console.log(`name of the book is${this.title}`); 
 
}Corebook.prototype.summary = function(author) { 
 
console.log(`${this.title} is writtenby ${this.author}`); 
 
}let Book = function(title, author) { 
 
Corebook.call(this, title, author) 
 
}Book.prototype = Object.create(Corebook.prototype); 
 
let book1 
 
= new Book('TheAlchemist', 'Paulo Coelho');book1.title(); 
 
> name of the book is The Alchemistbook1.summary(); 
 
> The Alchemist is written by Paulo Coelho 

在上面的代码中,Book 的实例有一个原型的副本,能够链接到Book的原型,而Book的原型又链接到Corebook的原型。

6. 多态

在不同的对象上使用同一方法,并让每个对象具有自己的表现形式或形态的能力,称为多态。

letbook1 = function () {} 
 
book1.prototype.summary = function() { 
 
return "summary of book1" 
 
}let book2 = function() {} 
 
book2.prototype = Object.create(book1.prototype); 
 
book2.prototype.summary = function() { 
 
return "summary of book2" 
 
}let book3 = function() {} 
 
book3.prototype = Object.create(book1.prototype); 
 
book3.prototype.summary = function() { 
 
return "summary of book3" 
 
} 
 
var books = [new book1(), new book2(), new book3()]; 
 
books.forEach(function(book){ 
 
console.log(book.summary()); 
 
});> summary of book1 
 
> summary of book2 
 
> summary of book3 

对象之间的关系将由关联、聚合和组合定义。

7. 关联

关联是两个或多个对象之间的关系。每个对象都是独立的。换句话说,关联定义了对象之间的多重性:一对一、一对多、多对一、多对多。

functionBook(title, author) { 
 
this.title = title; 
 
this.author = author; 
 
} 
 
const book1 = new Book ('Hippie', 'Paulo Coelho'); 
 
const book2 = new Book ('TheAlchemist', 
 
'Paulo Coelho'); 
 
book2.multiplicity 
 
= book1 

book1 赋值于book2的属性多样化,显示对象book1 和 book2之间的关系。两者都可以独立添加和删除。

e6zQvem.jpg!web

8. 聚合

聚合是关联的特例。在两个对象之间的关系中,一个对象可能比另一个更重要。换句话说,当一个对象比另一个拥有更多的所有权时,这就是聚合。对象所有者通常称为聚合,被所有者称为组件。聚合又叫“Has-a”关系。

functionBook(title, author) { 
 
this.title = title; 
 
this.author = author; 
 
} 
 
const book1 = new Book ('Hippie', 'Paulo Coelho'); 
 
const book2 = new Book ('TheAlchemist', 'Paulo Coelho'); 
 
let publication = { 
 
"name": "new publicationInc", 
 
"books": [] 
 
}publication.books.push(book1); 
 
publication.books.push(book2); 

book1 和 book2 被添加到对象publication下设的books中。如果在book1和book2 运行之后删除publication,则 Book和 publication 都将独立运行。

VZb6FvB.jpg!web

9. 组合

组合是聚合的一种特殊情况。一个对象包含另一个对象,并且被包含的对象脱离后无法生存。

let Book= { 
 
"title": "TheAlchemist", 
 
"author": "PauloCoelho", 
 
"publication": { 
 
"name": "newpublication Inc", 
 
"address":"chennai" 
 
} 
 
} 

这里属性publication与 Book 对象有严格的限制,publication不能没有Book对象。如果Book的id被删除,则publication也将被删除。

重组合轻继承

继承指一个对象基于另一个对象的情况。例如,book1继承了标题、作者和结语等书籍的属性和方法,所以它建立了book1 is-a Book关系。

组合是收集单一对象并将它们组合起来构建更复杂的对象。为构建book1,需要一些方法,比如纸和笔。因此book1 has-a paper and a pen关系随之出现。

constgetTitle = (data) => ({ 
 
title : () => console.log(`title :${data.title}`) 
 
});const getAuthor = (data) => ({ 
 
author : () => console.log(`author:${data.author}`) 
 
});const getSummary = () => ({ 
 
summary :() => console.log(`booksummary need to 
 
update.`) 
 
});const Book = (title, author) => { 
 
const data = { 
 
title, 
 
author 
 
} 
 
return Object.assign({}, 
 
getTitle(data), 
 
getAuthor(data), 
 
getSummary() 
 
) 
 
}let book1 = Book('The Alchemist', 'Paulo Coelho'); 
 
book1.title(); 
 
> "title : The Alchemist" 

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK