前端学习笔记

原型与原型链

2019-07-27  本文已影响11人  _ClariS_

公用属性

我们知道,所有对象都有 toString 和 valueOf 属性,但如果给每一个对象都分配一个 toString 和 valueOf ,会十分地占内存,如图

每一个对象都分配 toString 和 valueOf

显然这么做很蠢。

因此,JS 的做法是把 toString 和 valueOf 放在一个对象里(暂且叫做公用属性组成的对象),然后让每一个对象的 _ _ proto _ _ 存储这个「公用属性组成的对象」的地址。

举个栗子
执行 o1.toString() 时,首先进入对象 o1 查找是否存在 .toString 属性,如果没有,再通过 _ _ proto _ _ 进入所有对象的公用属性中找到 toString 函数

同时,这时候如果再声明一个对象 o2 ,我们会发现虽然 o1 与 o2 不相等,但却有 o1.toString === o2.toString,这也说明了对象确实是存在公用属性的

另外,除 Object 对象之外,Number、String、Boolean 对象都分别有自己独有的公用属性,以 Number 对象为例:

每个实例对象( object )都有一个私有属性(称之为 _ _ proto _ _ )指向它的构造函数的原型对象(prototype )。该原型对象也有一个自己的原型对象( _ _ proto _ _ ) ,层层向上直到一个对象的原型对象为 null。根据定义,null 没有原型,并作为这个原型链中的最后一个环节。

树形结构图

上图中红色的连线就被称之为原型链

代码

即便不写代码,浏览器也是会有 prototype 的,且浏览器的 prototype 无法被修改

image.png

注意:Object.prototype对象也有_ _ proto _ _属性,但它比较特殊,为null

重要公式

通用公式

var 对象 = new 函数()
对象.__proto__ === 对象的构造函数.prototype

注意:
一、构造函数的概念:

任何函数都可以当成构造函数 function CreateFunc(){ }
只要把一个函数通过new的方式来进行调用,我们就把这一次函数的调用方式称之为:构造函数的调用
new CreateFunc(); 此时CreateFunc就是一个构造函数
CreateFunc(); 此时的CreateFunc并不是构造函数
也可以说,构造函数就是返回一个新的对象的函数

二、七种基本数据类型中只有 number、string、boolean、object(array、function)分别有相应的构造函数 Number()、String()、Boolean()、Object()、Array()、Function(),undefined和null是没有构造函数的。

推论

var number = new Number()
number.__proto__ = Number.prototype
注意大小写,number 和 Number 是不同的
//
var object = new Object()
object.__proto__ = Object.prototype
//
var function = new Function()
function.__proto__ = Function.prototype

另外,所有函数都是由 Function 构造出来的,所以

Number.__proto__ = Function.prototype // 因为 Number 是函数,是 Function 的实例
Object.__proto__ = Function.prototype // 因为 Object 是函数,是 Function 的实例
Function.__proto__ == Function.prototye // 因为 Function 是函数,是 Function 的实例!
上一篇 下一篇

猜你喜欢

热点阅读