什么是原型和原型链?
在讲这个之前,我们先把这个名词忘掉,不要试图从字面意思去理解这个词,它只是几个汉字,我们可以把这个看成[ab]和[abc]。
在这之前我们先来了解一些必要的知识
数据类型
js里 数据类型分为 7 种:
string number null undefined object Boolean symbol
数据类型又分两种:简单数据类型 复杂数据类型 。 复杂类型是由简单类型组成的。
复杂数据类型只有object
内存:栈内存 堆内存
这个就不从头开始介绍了,我们可以简单的把这个想象成这个虚拟的空间, 我们把这个分为两个部分:栈内存部分,堆内存部分。
一般的,当我们创建一个新的对象时,简单的数据类型的值直接存在栈内存中。 复杂数据类型的值存在堆内存中,但是在栈内存中会存一个地址,好让我们能在堆内存中找到它。
1 与 new Number(1) 的区别
当我们 var a1 = new Number(1) js创建了一个对象(哈希),除了一个PrimitiveValue
同时还有一个可以点开的属性 __proto__:Number, 这个属性中包含了另一些属性
这些属性中有一些我们可以看懂的 toString 它指向一个toString函数 和一个 valueOf属性和它的函数
我们可以调用这些方法得到一些返回值
当我们 用var a2 = 1 创建一个对象时候 我们同样可以调用 toString() valueOf() ,这是为什么呢?
因为 当我们var a2 = 1 写下这行代码的时候 它还只是个简单类型 它的值 直接存在栈内存中
但我们写下 a2.toString()的时候 它就会被一个临时对象(temp)替代 这个对象 跟 temp = new Number(1) 完全相同
这样它就能想a1一样 调用这些属性,当你完成这些操作得到返回值时候这个临时对象就会被销毁。
所以 var a = 1 和 var a = num Number(1) 唯一的区别就是 后者比前者写起来麻烦 除此之外没有任何区别。
共用属性
我们再 var b = new Number(2) 跟 a1 比较
我们可以看到 除了PrimitiveValue 不一样之外 其他部分一样 。
因此我们可以知道__proto__:Number 就是number 的共用属性
JS 内存是很稀缺的 js不可能每次创建一个number 对象 就写一遍这个属性 这样非常浪费空间
所以JS 把这些共有属性存放在一个地方 当我们需要的时候 就通过__proto__:Number 找到它。
我们会注意到 在__proto__:Number 里面 还有一个__proto__:Object 这个里面 是所有对象的共有属性
__proto__:Object 里面还会指向其他的共有属性吗 没有了 __proto__:Object 里面的 __proto__ 指向的是null
这些共用属性是哪里来的
这些共有属性不是你穿件对象时才出现的而是你一打开浏览器就存在的
当我们打开浏览器 ,浏览器就会自动创建一个全局对象global(window) window对象会创建很多方法 其中就包括 number() String()等等
这些不同的方法 构造了 不用类型的共用属性 然后供我们调用 这些构造出来的共用属性 我们就叫做 原型(prototype)
__proto__ 为了引用共用属性用的。 我们把一层一层引用共用属性的链接 叫做 原型链
对象的 __proto__ 指向的就是 创建这个对象的 函数构造的prototype