前言
工欲善其事,必先利其器。
大家好,我是龙哈哈。一个 Java
,JavaScript
两栖动物。
本篇是 FuckingJavaScript
系列的第二篇,我们来一起回顾一下 原型
的相关知识。
什么是原型编程
为什么其他的 面向对象
语言没有 原型
,JavaScript
却要有呢?
带着这个疑问,我们去查阅下JavaScript发展史
的相关资料
JavaScript诞生史
爸爸是初代浏览器王朝的王者
网景(Netscape)
没错,就是window.navigator.appName
的那个Netscape
。
Netscape
招募来了Scheme
专家Brendan Eich
,想把Scheme
嵌入进浏览器中
这也就解释了JavaScript中函数是第一公民
的原因。
在
Javascript
出生之前,Netscape浏览器
支持Java程序
运行,所以设计的初衷就是要设计出一个与Java相似
,但是比Java简单
的语言。
这就是命名 Java
+Script
的由来,祖上还是和Java
有一定渊源的
设计时间
从开始
到结束
,只用了十
天。
设计思路
- 借鉴
C
的基本语法 - 借鉴
Java
的数据类型和内存管理 - 借鉴
Scheme
,将函数提升到第一等公民
的地位 - 借鉴
Self
,使用基于原型(prototype)
的继承机制
JavaScript是多种语言风格的混合产物,既包含了函数式编程又有面向对象编程,从诞生的那天起,就自带
争议
属性
Netscape
和 Brendan Eich
可能也没有想到,JavaScript
将来会成为全球最流行的编程语言。
对JavaScript Coder
来说,奇妙的旅程,就此开始。
什么是原型编程
原型编程
是 面向对象编程
的一种风格和方式。
在原型编程中,行为重用(在基于类的语言通常称为
继承
)是通过复制已经存在的原型对象的过程实现的。这个模型一般被认为是无类的、面向原型、或者是基于实例的编程。
简单来说,这种风格是在不定义class
的情况下创建一个 object
。
Self语言
是原型编程这一派的祖师爷, JavaScipt
在设计的时候采用了这种编程方式。
JavaScipt原型的三座大山
- prototype
- __ proto __
- constructor
首先要明确
prototype
是Function
独有__ proto __
,constructor
是Object
独有
经典祭祖图
一脸懵逼的进来,一脸懵逼的出去
不慌,我们先看一段代码
function Hero(name) {
this.name = name;
}
// Hero 的 prototype
Hero.prototyoe.country = 'demacia';
// 创建实例
var garen = new Hero('garen');
var jarvanIV = new Hero('jarvanIV');
// 实例可继承函数原型对象的属性
console.log(garen.country); // demacia
console.log(jarvanIV.country); // demacia
// 函数的原型对象
console.log(Hero.prototype);
// 对象的原型
console.log(garen.__proto__);
console.log(jarvanIV.__proto__);
复制代码
prototype
函数的原型对象,Function
独有,指向了一个对象,对象是 调用该函数而创建的实例的原型__proto__
prototype
本身也是个 Object
,所以 prototype
也有 __proto__
和 constructor
这里可能会有同学疑惑,我们带着疑问接着往下看
__ proto __
对象的原型,Object
独有,指向了一个对象,对象是 创建该对象的函数的原型对象,
// 对象的原型 和 函数的原型对象,指向同一地址,是相同的对象
console.log(garen.__proto__ === Hero.prototype);
复制代码
我们上面说 prototype
也是对象,所以也有 __proto__
,所以延伸一下就有
// Hero.prototype是个对象
// 对象的原型就指向创造ta的函数的原型对象,即 Object 的 原型对象
console.log(Hero.prototype.__proto__ === Object.prototype); // true
// 终点站到了 null
console.log(Object.prototype.__proto__ === null); // true
复制代码
对象之间通过__proto__
连接起来,这就是原型链
。当前对象上不存在的属性方法
可以通过__proto__
一层层往上查找,直到终点站 null
我们常用的不同数据类型的方法都是靠 __proto__
继承而来
constructor
构造函数,Object
独有,顾名思义,指向了函数本身
// 函数的原型对象的构造函数,指向函数本身
console.log(Hero.prototype.constructor === Hero); // true
复制代码
函数本身也是个对象,所以也有 __proto__
,所以延伸一下就有
// 命名函数的 原型 指向 Function 的原型对象
console.log(Hero.__proto__ === Function.prototype); // true
// Function原型对象的原型,指向 Object 的原型对象
console.log(Function.prototype.__proto__ === Object.prototype); // true
// 终点站到了 null
console.log(Object.prototype.__proto__ === null); // true
复制代码
总结
JavaScript
借鉴Self
,使用基于原型(prototype)
的继承机制Object
特有__proto__
和constructor
,Function
特有prototype
prototype
也是个Object
,也有__proto__
和constructor
Object
的__proto__
指向创建该对象的函数
的prototype
- 对象之间通过
__proto__
连接起来,当前对象上不存在的属性方法
可以通过__proto__
一层层往上查找,直到终点站null
,通过__proto__
将不同对象连接起来的链路就是原型链
constructor
指向对象的构造函数,所有函数(也可看做是对象)最终的构造函数
都指向Function
最后
三人行,必有我师焉
掘金不停,代码不止
互相学习,共同进步
文中如有错误,欢迎在评论区指正。
如果这篇文章对你有所帮助,欢迎点赞、评论和关注。
系列文章
- 【FuckingJavaScript系列】数据类型,你真的掌握了吗?
- 【FuckingJavaScript系列】原型编程,你真的理解了吗?
- 【FuckingJavaScript系列】函数编程,你真的熟练了吗?
- 【FuckingJavaScript系列】异步编程,你真的学会了吗?
- 【FuckingJavaScript系列】事件循环,你真的明白了吗?
- 【FuckingJavaScript系列】垃圾回收,你真的清楚了吗?