JavaScript 基础
Document
运算符
深入数据和类型
函数进阶
原型、继承
类
浏览器存储
Web API
事件
错误处理
异步编程
网络请求
模块
练习
实例
工具与规范
软件架构模式
设计模式
很多时候我们需要创造一些同类型的对象,在之后可以统一地处理,
$$jsdemo$$
$$edit$$
let mingren = {
name: "鸣人",
score: 56,
}
let kenan = {
name: "柯南",
score: 98,
}
let students = [mingren, kenan]
for (let student of students) {
alert(`${student.name}同学的分数是 ${student.score}`)
}
这种定义方法需要写很多重复的代码,并且属性名写错就会造成严重的灾难。
比如以下的代码拼错了一个单词就导致程序异常:
$$jsdemo$$
$$edit$$
let mingren = {
name: "鸣人",
score: 56,
}
let kenan = {
name: "柯南",
scroe: 98, // 这里拼错了,导致程序不正常
}
let students = [mingren, kenan]
for (let student of students) {
alert(`${student.name}同学的分数是 ${student.score}`)
}
于是乎,我们想到了可以在通过函数统一地创建对象,如下:
$$jsdemo$$
$$edit$$
function createStudent(name, score) {
return {
name,
score,
}
}
let mingren = createStudent("鸣人", 56)
let kenan = createStudent("柯南", 98)
let students = [mingren, kenan]
for (let student of students) {
alert(`${student.name}同学的分数是 ${student.score}`)
}
为了明显地区分出这种这种创造了一个对象的函数,便有了 new
运算符。
构造函数
当我们用 new
运算符调用一个函数时,这个函数就被称为一个构造函数。构造函数会创造一个对象,在构造函数中可以使用 this
访问被创造出来的对象,对象在函数执行完成后返回。
通过 new
运算符改造上面的代码:
$$jsdemo$$
$$edit$$
// 构造函数首字母习惯大写
function Student(name, score) {
// 使用 new 运算符
// this = {}
this.name = name
this.score = score
// return this
}
let mingren = new Student("鸣人", 56)
let kenan = new Student("柯南", 98)
let students = [mingren, kenan]
for (let student of students) {
alert(`${student.name}同学的分数是 ${student.score}`)
}
当一个函数被使用 new
操作符执行时,它按照以下步骤:
- 一个新的空对象被创建并分配给
this
。 - 函数体执行。通常它会修改
this
,为其添加新的属性。 - 返回
this
的值。
$$tip
构造函数首字母习惯大写,这是一个约定俗成的习惯。
$$
构造函数的 return
通常构造函数不用写 return
,它会默认返回创造的 this
对象。如果存在 return 语句的话:
- 如果
return
返回了一个对象,则返回一个对象而不是this
。 - 如果
return
返回了一个原始类型,则忽略并依旧返回this
。
$$jsdemo$$
$$edit$$
function Student(name, score) {
this.name = name
this.score = score
return { cat: "加菲" }
}
let mingren = new Student("鸣人", 56)
console.log(mingren) // {cat: '加菲'},返回了创建的对象
function Student2(name, score) {
this.name = name
this.score = score
return 123
}
let kenan = new Student2("柯南", 98)
console.log(kenan) // {name: '柯南', score: 98},忽略原始值依旧返回 this
实战:单例模式
依照以上特性,我们来完成一个编程设计模式中的单例模式。
单例模式用于创建那些程序中仅允许出现一次的对象。
$$jsdemo$$
$$edit$$
// 单例模式
function SchoolMaster(name) {
// 如果不存在则初始化
if (window.$schoolMaster == undefined) {
window.$schoolMaster = {
name,
}
}
return window.$schoolMaster
}
let schoolMaster = new SchoolMaster("邓布利多")
let schoolMaster2 = new SchoolMaster("王校长")
console.log(schoolMaster.name) // 邓布利多
console.log(schoolMaster2.name) // 邓布利多
练习
- 补全以下实例。
function People(fisrtname, lastname) {
// 补全代码
}
const ailun = new People("艾伦", "耶格尔")
alert(ailun.getFullname()) // 艾伦·耶格尔
const bingzhang = new People("利威尔", "阿克曼")
alert(bingzhang.getFullname()) // 利威尔·阿克曼
$$answer
$$jsdemo$$
$$edit$$
function People(fisrtname, lastname) {
this.getFullname = function () {
return `${fisrtname}·${lastname}`
}
}
const ailun = new People("艾伦", "耶格尔")
alert(ailun.getFullname()) // 艾伦·耶格尔
const bingzhang = new People("利威尔", "阿克曼")
alert(bingzhang.getFullname()) // 利威尔·阿克曼
$$
- 补全以下代码,创建两个独立的计数器。
function Counter() {
// 补全代码
}
const conterA = new Counter()
const conterB = new Counter()
alert(`A: ${conterA.count()}`) // 1
alert(`A: ${conterA.count()}`) // 2
alert(`B: ${conterB.count()}`) // 1
alert(`B: ${conterB.count()}`) // 2
$$answer
$$jsdemo$$
$$edit$$
function Counter() {
this.counter = 0
this.count = () => ++this.counter
}
const conterA = new Counter()
const conterB = new Counter()
alert(`A: ${conterA.count()}`) // 1
alert(`A: ${conterA.count()}`) // 2
alert(`B: ${conterB.count()}`) // 1
alert(`B: ${conterB.count()}`) // 2
$$