理解JavaScript原型和原型链 (资料整理,个人学习)
(原文链接https://www.cnblogs.com/piaobodewu/p/13795077.html)
精典图
注意:
(prototype-原型, _proto_-继承)
1:只有Functions集合中的function有prototype属性。
2:function的prototype指向Prototypes集合中的实例。
3:Prototypes集合中的实例constructior属性指向Functions集合中的function。
4:(new xx())对象中有_proto_属性。
5:(new xx())对象_proto_指向Prototypes集合中的实例
6:Functions集合中的function在new 的同时都继承(_proto_)同一个Prototypes集合中的function的实例。
一切起源于null
机器1号可不得了,它是JS世界的第一个对象,它是真正的万物始祖。它拥有的性质,是所有的对象都有的。__proto__
是什么呢?是“生”的意思,或者换成专业点的叫法“继承”.
有中生有
一生二,二生三,三生万物
通过object创造对象,Object制造对象时候,需要有一个模版,现在只有机器1号,它就取了机器1号当模版。图中的prototype
就代表模板对象。
通过new
命令。按下“new”按钮,新的对象就造出来了。var obj = new Object();
Object通过(prototype)
模板创造new对象,对象通过(_proto_)继承模板,
有生万物
(注:__proto__
用[p]
来代替)
Object
也指向了机器2号,这是因为机器2号是负责造对象的,当然也负责造Object
对象
Object有自己的模板:机器1号。而String、Number、Boolean、Array
它们有模板吗?
其实机器2号在创建它们的时候并不是直接创建它们的,而是先创建了对应对象的机器作为模板,然后再由各自的机器来创建它们。
机器2号总体负责制造所有的对象,包含Object、String、Number、Boolean、Array,甚至还有之后的Function。当然它只是负责制造,并不一定会亲手去制造对象,可以通过制造对应的机器来帮助它制造对象
- 机器1号制造了机器2号,机器2号总体负责各种对象的制造
- 但是机器2号并不是直接造各种对象,而是通过先建造对应的机器(模板),再由对应的机器来制造对象(继承)。如:对于String,
机器2号
先制造了机器String号
,然后由机器String号
来制造String,机器2号
只负责总体控制 - 虽然机器2号制造了各种各样的机器,但是因为机器2号是由机器1号制造的,所以这些被制造的机器所属权还是归于机器1号的,毕竟机器1号是始祖级的。
- 对象和对应的机器,通过
prototype
来连接。如:对于String,机器2号
和String
通过prototype
连接 - 每个机器都有且只有一个的对象,每个对象也都有且只有一个机器作为模板
万物缺活力-Function的制造
- 它是由机器2号亲手制造的,所以它们之间有
prototype
相连 - 而机器2号又是制造所有对象的负责者,所以它们之间有
__proto__
相连 - Function.__proto__ === Function.prototype
- 机器1号 = Object.prototype(机器1号是Object的模板)
- 机器2号 = Function.prototype(机器2号是Function的模板)
- 机器String号 = String.prototype(机器String是String的模板)
- Function对象作为一个函数,就会有prototype属性,该属性将对应”function () {}”对象。
Function对象作为一个对象,就有__proto__属性,该属性对应”Function.prototype”, - 也就是说,”Function._proto_ === Function.prototype”。
世界动起来
刚造出来的Function机器很难用,用法就像下面这个
let Foo = new Function("name", "console.log(name)");
Foo('dellyoung'); // 控制台打印出:dellyoung
语法糖
function Foo(name) { console.log(name); }
Foo('dellyoung'); // 控制台打印出:dellyoung
以造Foo()
为例,于是JavaScript的世界的变成了下面的样子:
- 机器Foo()号 =
Foo.prototype
- [p] =
__proto_
Function这个对象比较特殊,它new出来后,就是一个全新的对象了,function Foo()
(注意:它等价于 let Foo = new Function()
)和Object
、String
、Number
等这些对象一样,都是对象。
既然都是对象,当然function Foo()
也是由机器2号来控制制造的,但是机器2号很忙,它没有精力直接制造function Foo()
,机器2号是通过制造出一个制造function Foo()的机器
来制造function Foo()
。
咱们称制造function Foo()的机器
为机器Foo()号
当然既然是机器,所以机器Foo()号
也是由机器1号
控制的
回到现实
可以被用来new
的对象或函数,我们都可以称之为构造函数,每个构造函数都和它的机器(也就是XXX.prototype
)通过constructor
相连,我们来画出构造函数和它们的constructor
正式的语言总结一下就是:?
- 子类的__proto__属性,表示构造函数的继承,总是指向父类。
- 子类prototype属性的__proto__属性,表示方法的继承,总是指向父类的prototype属性。
- 原型也是一个对象,通过原型可以实现对象的属性继承
- 对于所有的对象,都有__proto__属性,这个属性对应该对象的原型.
var
p =
new
Person(
'张三'
,20);
1. var p={}; 初始化一个对象p。
2. p._proto_=Person.prototype;,将对象p的 __proto__ 属性设置为 Person.prototype
3. Person.call(p,”张三”,20);调用构造函数Person来初始化p。关于call/apply使用
总结:
1. 所有的对象都有__proto__属性,该属性对应该对象的原型.
2. 所有的函数对象都有prototype属性,该属性的值会被赋值给该函数创建的对象的_proto_属性.
3. 所有的原型对象都有constructor属性,该属性对应创建所有指向该原型的实例的构造函数.
4. 函数对象和原型对象通过prototype和constructor属性进行相互关联.
(原文地址:https://zhuanlan.zhihu.com/p/23026595)
<什么是原型>
JavaScript 中,万物皆对象!但对象也是有区别的。分为普通对象和函数对象,Object ,Function 是JS自带的函数对象。
每个对象都有原型(null和undefined除外),你可以把它理解为对象的默认属性和方法。
Object:Object是一个函数对象,Object的原型就是一个Object对象,它里面存在着一些对象的方法和属性,例如最常见的toString方法。
新建对象:用new Object或者{}建的对象是普通对象,它没有prototype属性,只有__proto__属性,它指向Object.prototype。
Array:Array也是一个函数对象,它的原型就是Array.prototype,它里面存在着一些数组的方法和属性,例如常见的push,pop等方法。
Function:Function也是一个函数对象,但它有点特殊,它的原型就是一个function空函数。
自定义函数:它的原型就是你给它指定的那个东西。如果你不指定,那它的原型就是一个Object.prototype。
<什么是原型链>
在JavaScript 中,每个对象都有一个指向它的原型(prototype)对象的内部链接。这个原型对象又有自己的原型,直到某个对象的原型为 null 为止(也就是不再有原型指向),组成这条链的最后一环。这种一级一级的链结构就称为原型链(prototype chain)。
JavaScript 对象是动态的属性“包”(指其自己的属性)。JavaScript 对象有一个指向一个原型对象的链。
当试图访问一个对象的属性时,它不仅仅在该对象上搜寻,还会搜寻该对象的原型,以及该对象的原型的原型,依此层层向上搜索,直到找到一个名字匹配的属性或到达原型链的末尾。
当你用new Object或者直接定义一个对象时,它的原型链就是:
o ==》 Object.prototype ==》 null;o._proto_==Object.prototype
访问o上没有的属性或方法时,JS会往Object.prototype上寻找该属性和方法。
如果有则直接返回,如果没有,方法则报错,这个方法未定义,属性则返回undefined
o.__proto_指向原型对象,
原型对象
被赋值给创建的对象_proto_属性中.o对象没有prototype
Person所有对象都有公共属性-Person.prototype = {age:24};
Person是构造函数,
tsrot函数对象(构造对象)。用构造函数(构造函数我们一般首字母大写)建立一个对象时,它的原型链就是
tsrot ==》 Person.prototype ==》 Object.prototype ==》 null
tsrot.__proto__=Person.prototype;
Person.prototype.__proto__=Object.prototype;
Parent和child都是构造函数,
fun是一个函数对象,它是由Function构造函数new的
<prototype与__proto__>
在Javascript中,每个函数都有一个原型属性prototype指向自身的原型,而由这个函数创建的对象也有一个__proto__属性指向这个原型,
而函数的原型是一个对象(函数点prototype也是一个普通对象,Function.prototype除外,它是函数对象,但它很特殊,他没有prototype属性),
所以这个对象也会有一个__proto__指向自己的原型,这样逐层深入直到Object对象的原型,这样就形成了原型链。
普通对象没有prototype,但有__proto__属性。
(原文地址https://www.cnblogs.com/tg666/p/12059205.html)
Person 就是一个构造函数,使用 new 创建了一个实例对象 person
prototype
每个函数都有一个 prototype 属性
proto
每一个 javaScript 对象(null除外)都具有的一个属性叫 proto ,这个属性会指向该对象的原型
constructor
每一个原型都有一个 constructor 属性指向关联的构造函数,实例原型指向构造函数
实例与原型
原型与原型
Person.prototype也是一个对象,具有_proto_属性指向Object的原型
原型链