前言
在很长很长的时间, 我对js的原型以及原型链很懵懂,
为什么 Object.__proto__ === Function.prototype
而 Function.prototype.__proto__ === Object.prototype
这一现象让我觉得非常困惑,深深的觉得它在套娃,我不断的在这个循环里打转,无法自拔,看一会感觉自己理解了,但是后面换一种问法,我又开始绕进去了,我想我并没有真正理解,知其一不知其二,所以我决定用文档的形式,或者是说以述说,“为什么” 的角度分享出来,知其因,知其果。
什么是原型对象
通常我们把函数的 prototype 称作为原型对象,每个函数都会有prototype。
function x() {}
console.log(x.prototype) // 原型对象
什么是原型链
原型与原型层层连接的过程称为原型链。
// 这里我们先把复杂的Function,与object抛开,只讨论以下代码的链路连接
function Y(name,age) {
this.name = name;
this.age = age;
}
// 给Y的原型对象添加 color属性为 red
Y.prototype.color = 'red'
// 改变Y1原型对象的指向,指向这个生成的实例
function Y1(name) {
this.name = name;
}
Y1.prototype = new Y('小明', 29);
// 基于Y2.prototype,构造出实例,这个实例对象的 __proto__ 引用了Y2.prototype
const child = new Y1('小红');
const childCopy = {};
// !!!对象没有prototype!! 思考: 为什么对象没有__proto__呢?
// 更改 childCopy .__proto__ 的指向 为child.__proto__
childCopy.__proto__ = child.__proto__;
console.log(child.color, childCopy.color) // red red
console.log(child.name, childCopy.name) // 小红 小明
待补图
为什么我们能直接调用 数组/字符串 的“方法” ?
你有没有思考过一个问题,为什么我们能直接调用 [].map, 'x'.toString()...等,我们创建一个变量,有两种方式,一种是声明,一种是构造形式, 他们生成的对象都是一样的,但是他们的表现却会不同。
var myStr = 'I am a stringI am a string'; // 声明式
typeof myStr; // string
var myStrObj = new String('I am a string'); // 构造式
typeof myStrObj; // object;
myStr + myStrObj // I am a stringI am a string
可以看见使用声明式 “I am a string” 并不是一个对象,它只是一个普通的字符串,字符串就是数据,在必要时,注意是必要时,比如:访问字符串的方法(长度,或者splice...等等),js引擎会把它转换成String对象。
上面的描述不够直观,我一直在想,用一种什么样的方式表达我想说的,直到我再次回顾了《你不知道的js》这本书,作者在书中写着这段话让我突然豁然开朗想要表达些什么。
面向对象编程强调的是数据和操作数据的行为本质上是互相关联的(当然,不同的数据有不同的行为)。 因此好的设计就是把数据以及和它 相关的行为打包(或者说封装)起来。 这在正式的计算机科学中有时被称做数据结构。
通常我们不关心数据是什么,而是可以对数据做什么,所以可以应用在这种数据上的行为(计算长度,添加数据,搜索,等等..),都被设计成string方法, 所有的字符串都是一个 String。
通俗点来说,你可以把访问方法的过程,想象成装箱和拆箱。
把 new String 看作是一个箱子,箱子里装着字面量 ('I am a string') , 比如:当你使用两个字符串相加时,js引擎会拆箱,把箱子里的字面量取出使用(这里涉及到js的运算机制,我们不展开), 而使用的是声明式,这个时候访字符串的方法,js引擎会把字面量装箱(方法都在对象上面,字面量只是数据)。
注意:这些状况都是在需要使用的时候,才会进行的操作,如果你不使用它,那它不会发生任何的改变。
重要:我们定义所有的声明都是继承对应数据类型的方法
tip: 通常我们并不会使用构造式这么去创建一个对象,我们一般都会使用声明式创建对象,
绝大多数的内置对象也是这么做的。
引流标题:工作了五年我竟然还不懂js原型对象和原型链!!这一次彻底搞懂什么是原型对象/