JS源码

本篇文章将详细介绍JS面向对象编程

1.JS创建实例对象的四种方式

方式一

1
obj = {}

方式二

1
obj = new Object()

方式三

1
2
3
4
5
6
7
8
9
10
11
// 工厂函数
function Person(name, age){
let obj = {}
obj.name = name
obj.age = age
return obj
}


p = new Person('xyz', 18)
console.log(p.name)

方式四

1
2
3
4
5
6
7
8
// 构造函数
function Person(name, age){
this.name = name
this.age = age
}

p = new Person('xyz', 18)
console.log(p.name)

2.内置构造函数和自定义构造函数

内置构造函数如Object | Function | Array | Date

自定义构造函数

1
2
3
4
5
6
7
8
// 构造函数
function Person(name, age){
this.name = name
this.age = age
}

p = new Person('xyz', 18)
console.log(p.name)

3.实例对象

1
2
3
4
5
6
7
8
// 构造函数
function Person(name, age){
this.name = name
this.age = age
}

p = new Person('xyz', 18)
console.log(p.name)

p是一个实例对象,是由构造函数Person实例化出来的一个对象。

4.原型对象

JS中万物皆对象,所以构造函数Person也是一个对象。构造函数对象身上有一个属性prototype, 指向原型对象。

图解如下

img

5.给实例对象添加方法

1
2
3
4
5
6
7
8
9
10
11
12
13
// 构造函数
function Person(name, age){
this.name = name
this.age = age
}

Person.prototype.say = function(){
console.log('my name is ' + this.name)
}

p = new Person('xyz', 18)
console.log(p.name) // xyz
p.say() // my name is xyz

实际上是在原型对象身上绑定了一个方法say, 而不是直接在实例对象身上绑定say方法,这样做的目的是,当我们创建多个实例对象的时候,如果直接在实例对象身上绑定方法,会造成内存空间的浪费,并且say方法的代码得不到复用。

图解如下

img

如果在实例对象身上绑定say方法,示例代码如下

1
2
3
4
5
6
7
8
9
10
11
12
function Person(name, age){
this.name = name
this.age = age
this.say = function(){
console.log('my name is ' + this.name)
}
}

p1 = new Person('xyz', 18)
p2 = new Person('zs', 24)
console.log(p1.name) // xyz
console.log(p2.name) // zs

图解如下

img

6.prototype和proto

JS万物皆对象, 函数也是一个对象。

JS中所有函数都有一个自带的属性prototype, 这个属性指向原型对象。

JS中所有对象都有一个自带的属性__proto__, 这个属性指向构造函数的原型对象, 因为函数也是一个对象, 所以函数身上也有一个属性__proto__

图解如下

img

也就是说实例对象p身上有一个属性__proto__, 指向构造函数的原型对象。实例对象p是由构造函数Person实例化出来的。

这里我们可以验证一下

1
2
3
4
5
6
7
8
9
10
11
12
// 构造函数
function Person(name, age){
this.name = name
this.age = age
}

Person.prototype.say = function(){
console.log('my name is ' + this.name)
}

p = new Person('xyz', 18)
console.log(p.__proto__ === Person.prototype) // true

那么构造函数Person__proto__又指向哪里呢?

JS中所有函数都是**Function**的实例对象

图解如下

img

Person构造函数是Function的实例对象

那么构造函数的__proto__又指向哪里呢?

**Function**对象是自己的实例

所以Function身上的属性__proto__指向自身的原型对象

图解如下

img

7.原型对象上的proto

前面我们说过,JS中万物皆对象,对象身上都有一个自带的属性__proto__, 那么原型对象身上的__proto__又指向哪里呢?

原型对象上的proto指向Object原型对象

图解如下

img

那么问题又来了, Object原型对象身上是否有一个属性__proto__,是的,前面我们已经说过,JS中万物皆对象,对象身上都有一个自带的属性__proto__
那么Object原型对象身上的__proto__又指向哪里?

这里直接给出答案,Object对象身上的__proto__指向了null。也就是说已经到头了。所以Object原型对象又称为顶级对象

图解如下

img

到这里,我们基本上把JS面向对象的主要知识都理清了。

8.Object和Function构造函数

如果你对上面的所有过程都理解了,那么关于Object和Function之间的关系相信对你来说已经理解了。

Object构造函数是Function函数的实例,Function函数是自身的实例对象。

图解如下

img

9.对象访问机制(原型链)

JS中对象的访问机制,如果实例对象身上没有,那么会顺着原型链一直向上查找,直到Object顶级原型对象

我们来看下面的代码

1
2
3
4
5
6
7
8
9
10
11
12
// 构造函数
function Person(name, age){
this.name = name
this.age = age
}

Person.prototype.say = function(){
console.log('my name is ' + this.name)
}

p = new Person('xyz', 18)
p.say()

我们创建了一个实例对象p,在Person原型对象身上绑定了一个方法say

因为实例对象p并没有say方法,所以会顺着p.__proto__向上找。由于Person原型对象身上有say方法,所以我们可以直接调用。

如果没有在Person原型对象身上绑定say方法,那么会顺着Person原型对象往上查找,也就是找到了Object原型对象。这里我们可以给Object原型对象那身上绑定一个say方法来验证我们的想法。

1
2
3
4
5
6
7
8
9
10
11
12
// 构造函数
function Person(name, age){
this.name = name
this.age = age
}

Object.prototype.say = function(){
console.log('my name is ' + this.name)
}

p = new Person('xyz', 18)
p.say() // 正常打印 my name is xyz

如果Object对象身上也没有say方法呢,那么就会报错。

示例代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
// 构造函数
function Person(name, age){
this.name = name
this.age = age
}

// Object.prototype.say = function(){
// console.log('my name is ' + this.name)
// }

p = new Person('xyz', 18)
p.say() // p.say is not a function

10.this指向

this指向与实例对象调用有关, 也就是说谁调用this, this就指向谁

1
2
3
4
5
6
7
8
9
10
11
12
13
14
// 构造函数
function Person(name, age){
// this -> 当前实例对象
this.name = name
this.age = age
}

Person.prototype.say = function(){
// this -> p
console.log('my name is ' + this.name)
}

p = new Person('xyz', 18)
p.say()

11.construtor(构造器)

constructor是原型对象身上的一个属性,指向所属的构造函数

示例代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
// 构造函数
function Person(name, age){
this.name = name
this.age = age
}

Person.prototype.say = function(){
console.log('my name is ' + this.name)
}


p = new Person('xyz', 18)
console.log(Person.prototype.constructor) // [Function: Person]
console.log(p.constructor) // [Function: Person]

JS源码
http://cxycsx.vip/2023/08/31/其他/JS面向对象编程/
作者
程序员陈师兄
发布于
2023年8月31日
许可协议