语言: js

js version: v10.15.1

时间: 2019.4.25 15:34

这里我不说太长的话,去解释,不然会晕。
js 里面的原型是真的有一点的绕。记住这几句话就行了,我就不画图了,不然我感觉看图更晕。

  1. 万物皆对象。
  2. js 对象分为 函数对象 和 普通对象。
  3. 只有函数对象有 prototype ,所有的对象都有 proto 内置属性。
  4. prototype 其实是函数对象的一个实例。
  5. proto 是构造函数的原型对象。
  6. Function.prototype 它既是函数对象也是不普通对象。
  7. Object.prototype.proto 是个 null。

什么是函数对象?什么是普通对象?

解释:
通过 new Function 创建出来的对象是函数对象, 函数对象的实例是普通对象。
Object 就是通过 new Function 创建出来的。

1
2
console.log(typeof Object); // => function 这就是函数对象, 因为他们是js 内置创建出来的。
console.log(typeof Function); // => function

什么是函数的原型(prototype)

原型(prototype)其实是函数对象的实例,前面说过.
在代码中的体现如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
function A(){}
A.prototype.walk = function() {
console.log("walk");
}
console.log(typeof A.prototype); // object

// 这个其实和这个差不多。
function B() {}
B.prototype = {
walk:function() {
console.log("walk");
}
}

new A().walk(); // => walk
new B().walk(); // => walk

其实函数对象A 和 函数对象 B 是拥有一样的功能的。
你其实就可以想象成他就是一个普通对象而已,确切的说是函数对象的一个实例。

怎么判断这个对象到底是 函数对象还是普通对象?

一个简单的判断如下:

1
2
3
4
// 这个就是一个函数对象,你可能说这个是一个函数,但是它是 new Function() 创建出来的 所以它是一个函数的一个实例对象
console.log(typeof Object); // => function
// 这个就是一个普通对象
console.log(typeof new Object()); // => object

什么是proto?

proto 其实是函数对象的原型

举个例子解释这个是什么意思。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
// 为什么输出的 funciton 因为它就 等同于 Function.prototype
// 因为 Object 这个函数对象就是 根据 Funciton的函数原型构建出来的。
// 所以就有下面的输出了。
console.log(Object.__proto__); // => function // 函数对象
// 为了验证上面的说法
console.log(Object.__proto__ === Function.prototype); // true

console.log(Object.prototype); // => {}(object) // 函数对象的一个实例, 只有函数对象有 prototype

// 验证上面的说法
console.log(Object.prototype === Object.__proto__); // => false

// 再来一个 // 可能有人会问下面这个是什么东西
// 按道理 Oject.prototype 应该是 普通对象, 那普通对象的__proto__ 应该是 Obejct.prototype
// 但是不是,可能 这个 js 将这个里强行 置为 null;
// 这个是原型链的 顶端。 记住就好。
// 真的记住就好吗? 嗯哼,肯定不行。后面解释
console.log(Object.prototype.__proto__); // => null

// 函数对象的原型 应该是 普通对象.__proto__ 应该是 Object.prototype
console.log(Function.prototype.__proto__); // => {} 普通对象

// 强行按照上面 prototype 的概念, 这个应该也是个 Obejct 的 但是 他的输出确实 function
// 这个也是一个特殊的 记住就好, 但它也是 普通对象。
// 那就说明了 Function 自己 创建了自己
console.log(Function.prototype)

// 看下面这个例子
// 其实 a 就是 普通对象
// 我说了 所有对象都有 __proto__ 只有函数对象才有 prototype
let a = {}; // let a = new Object();
console.log(a.prototype); // null;

// __proto__ 指的是 构造函数的原型 或者说是函数对象的原型
// {} 和 new Object() 是一样的
// 所以 __proto__ 指向 Object.prototype
// 所以就是 {}
console.log(a.__proto__); // Object.prototype; === {}

// 验证上面的说法
console.log(a.__proto__ === Object.prototype); // true

啊哈,上面的例子有点多呵,要想学习东西就自己多想,多看吧。

那么这些东西到底能干嘛?

proto 和 prototype 能用来干什么?

这里我理解就是为了继承吧。
举个例子吧。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
let a = {};
console.log(a.__proto__); // => function => Object.prototype => Function.prototype
```
a 继承 Object 方法去哪里了 这个 __proto__ 内置属性可能是唯一可以追寻的 属性了。

所以我的理解就是 prototype 是个储存方法的容器,是函数对象储存方法的容器。
__proto__ 是连接 实例 和 函数对象之间的 桥梁

所以继承是靠 __proto__ 属性。

### 实现个继承的例子
验证一波上面的说法
```js
// 创建一个函数对象
function A () {
console.log('A 对象构造');
}

// 创建方法
A.prototype.walk = function() {
console.log('A walk');
}

// 静态方法
A.hello = function() {
console.log('A static method hello method is called');
}

A.hello();
new A().walk();

// 创建一个 函数对象 B
function B() {
this.name = "hello";
console.log('B对象构造')
}

// 这里只是将 A 函数对象的方法承载过来了
B.prototype.__proto__ = A.prototype;
// 继承静态变量
B.hello = A.hello;
// B的构造函数还是B
console.log(B.prototype.constructor === B); // true

new B().walk(); // B对象构造 A walk
B.hello(); // A static method hello method is called
console.log(new B().name); // 说明构造函数里面的 this 是实例的引用

总结

不知不觉有些的有点长了,有些复杂的感念只有多打印,多想,才行。
描述的少了,就描述的不一定准确。哎~;

  • 函数对象 => 类(class)
  • 普通对象 => 类(class)的实例
  • prototype => 类(class)的实例方法
  • proto => 类(class) 与 类 之间继承的桥梁
  • B 继承 A 通过 proto 将 A的实例方法注入到 B 中
  • Object , Function 函数对象
  • 默认 prototype 中会被 js 注入一些默认的方法 constructor

解答疑惑

Object.prototype.proto
一切皆是对象,上面可以参考继承的例子 这就话就是 Object 继承与谁 那当然是 null;
它是一切对象的根本

哭笑不得这是啥东西

1
2
3
4
5
6
7
8
9
10
11
// 说明 Function 继承 Object
console.log(Function.prototype.__proto__ === Object.prototype) // => ture

// Object 不继承 Function
console.log(Object.prototype.__proto__ === Function.prototype) // => false

// Object 是 Function 的 实例对象
console.log(Object instanceof Function); // true

// Function 是 Object 实例对象
console.log(Function instanceof Object); // true

很奇怪, 所有东西继承 Object
Object 是通过 Function 创建出来的
Function 继承 Object
Function 是 Object 的实例

猜测内部实现

1
2
3
4
5
6
7
8
9
let Object = new Function();

Object.prototype.__proto__ = null;
// 将 Function 实例对象的 注入到 Object 中
// 这里语法不对 , 只是为了 模拟
Object.prototype <= Function.prototype;

// Function 继承 Object
Function.prototype.__proto__ = Object.prototype;

至于 Function.prototype 为什么是 Function 这个可能有点特殊。 我暂时没有没有想到合理的解释,别的感觉,都能完全按这个理论解释清楚。

好了,下个月见.差点这个月没写文章.
啊哈.

最后更新: 2019年08月14日 11:22

原始链接: https://leng521.top/posts/5e8fa495/