理解JavaScript原型和原型链

时间:2020-10-15 08:18:00 来源:互联网 热度: 作者: 佚名 字体:

理解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())和ObjectStringNumber等这些对象一样,都是对象。

既然都是对象,当然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的原型

 

 

 原型链