面向对象,什么是对象?

​ 面向对象思想的创始者Alan Kay受分子生物学的启发,提出了面向对象这一思想。可以看出,这里所说的对象更像是研究对象。一个实验中,每一个小白鼠都是一个对象,即使是同一对照组,独立的研究个体就是一个单独的对象。再来看Alan Kay 发明smalltalk语言之前启蒙面向对象的simula语言: 据说,他们是为了模拟船只而设计的这种语言,并且对不同船只间属性的相互影响感兴趣。他们将不同的船只归纳为不同的类,而每一个对象,基于它的类,可以定义它自己的属性和行为。

所以在面向对象思想中是一个对象是一个更普适的概念。

在《面向对象分析与设计》这本书中,Grady Booch 替我们做了总结,他认为,从人类的认知角度来说,对象应该是下列事物之一:

  1. 一个可以触摸或者可以看见的东西;
  2. 人的智力可以理解的东西;
  3. 可以指导思考或行动(进行想象或施加动作)的东西。

那在面向对象编程中,对象指的又是什么?不同的编程语言有自己的特性,所以描述对象的思路又是不同的。

  1. 类 class

C++和Java等使用“类”概念。

这里更像是归类。看这里

  1. 原型 prototype

JavaScript使用的方式

这里是分类。有点像类比的概念。对象只描述自己与原型的区别: 🐟能游泳,甲鱼就是有壳,那作为鱼,它也一定能有游泳。

描述对象,怎么描述对象?描述对象的什么?对象的特征

1
2
3
1. 对象的唯一标识性
2. 状态:同一对象可能处于不同状态之下
3. 行为:对象的状态可能因为行为而变化

JavaScript如何描述对象

  1. 唯一标识性

一组实验有多只小白鼠,一只小白鼠就是一个对象,小白鼠的唯一标识性就是用编号来表达
那对象的唯一标识性在计算机语言中,通过内存地址的唯一性来表示

1
2
3
let x = { value: 0 }
let y = { value: 0 }
x == y // false
  1. 状态和行为

之所以这两个特征放在一起,是因为在JavaScript中,基于”first class” funciton,状态和行为统一抽象为”属性”。
JAVA中分别为 “属性” 和 “方法”;C++中称为“成员变量“ 和 ”成员函数“。

1
2
3
4
5
6
var x = {
a: 0,
b() {
console.log(this.a)
}
}
  1. 动态性

在javascript中,对象因为语言特性而存在高度的动态性:能够在运行时为对象添加和改变状态、行为。

运行时:
The time period to convert the source code to machine code is known as compile time. Tasks such as syntax analysis, semantic analysis, and code generation occur at compile time. Time period to run the executable file generated at compile time is referred as runtime.

那就是求值之后的计算过程??

1
2
3
let x = { a: 1 }
x.b = 2
console.log(x.a, x.b) // 1 2

两类属性

JavaScript用一组特征来描述对象:

  1. 数据属性

  2. value:属性的值

  3. writable:属性能否被赋值

  4. enumerable:for … in 能否枚举该属性

  5. configurable:该属性能否被删除或者改变

数据属性一般只关心它的”值”特征

  1. 访问器属性

  2. getter:函数或undefined,取属性值时调用

  3. setter:函数或undefined,设置属性值时调用

  4. enumerable:for … in 能否枚举该属性

  5. configurable:该属性能否被删除或者改变

  6. 例子

1
2
3
4
5
6
7
let x = { v: 0 }
x.k = "key"

Object.getOwnPropertyDescriptor(x, "v")
{value: 0, writable: true, enumerable: true, configurable: true}
Object.getOwnPropertyDescriptor(x, "k")
{value: "key", writable: true, enumerable: true, configurable: true}

所以我们一般通过字面量创建的对象得到的是数据属性,

要想定义访问器属性,即改变属性的特征:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
Object.defineProperty(obj, prop, descriptor)

Object.defineProperty(x, "c",
{value: "haha", writable: false, enumerable: false, configurable: true})

Object.getOwnPropertyDescriptor(x, "c")
// {value: "haha", writable: false, enumerable: false, configurable: true}

x // {v: 0, k: "key", c: "haha"}

x.c = "heihei"
x // {v: 0, k: "key", c: "haha"}

for (const item in x) {
console.log(item)
}
// v k

delete x.c

get和set

1
2
3
4
5
6
7
8
9
10
11
12
13
let y = { 
set b(state) { this.state = 2 },
get a() { return 0}
}

y.state = 3

state: 3
get a: ƒ a()
set b: ƒ b(state)
__proto__: Object

console.log(a) // 0

结论!:

JavaScript对象的运行时是一个“属性的集合”,属性以字符串或者Symbol为key,以数据属性特征值或者访问器属性特征值为value

  1. 对象是一个属性的索引结构(可以以较快的速度用key来查找value的字典)

上面的例子中,”c”是key,{value: "haha", writable: false, enumerable: false, configurable: true}是value