创建一个实例

使用构造函数创建一个实例

function Star(age,name) {this.age = agethis.name = namethis.sing = function(){console.log("我可以唱歌")}
}
let ldh = new Star(35,"刘德华")
console.log(ldh)//35,刘德华

理解构造函数里面的内容,构造函数里面是有静态成员和实例成员的

  1. 实例成员就是构造函数内部通过this添加的成员,在这里的sing、name和age就是实例成员,这个只能通过实例对象来访问,不能通过构造函数访问
    console.log(Star.sing)//undefind

  2. 静态成员,就是直接在函数本身上面添加的成员,只能通过构造函数访问
    Star.sex = “男”//这个就是静态成员
    console.log(Star.sex)//男
    console.log(ldh.sex)//undefined

虽然构造函数挺不错的,但是存在一个严重的内存浪费的问题,当我们使用构造函数创建多个实例的时候,如果这个函数里面有多个静态成员的函数,那么我们每一次创建实例对象,构造函数下的方法都会重新开辟一个内存空间去存放这些方法。

但是明明这些方法都是一个构造函数里面的,干嘛要这么麻烦,还要占用内存,所以出现了原型

构造函数里的东西

prototype

构造函数通过原型分配的函数是所有对象所共享的,js规定,每一个构造函数都有一个prototype属性,指向另外一个对象。注意这个prototype既是一个对象,这个对象的所有属性和方法,都是被构造函数所拥有

我们可以把那些不变的方法,直接定义在prototype对象上这样所有的实例都可以共享这个方法

所以上面的方法的改进应该是这样

function Star(age,name) {this.age = agethis.name = name
}
Star.prototype.sing = function(){console.log("我会唱歌")
}
let ldh = new Star(35,"刘德华")
ldh.sing//我会唱歌

因为prototype是一个对象,所以我们称构造函数的prototype为原型对象

__proto__

对象都会有一个属性__proto__,指向构造函数的prototype原型对象,之所以我们对象可以使用构造函数prototype原型对象的属性和方法,就是因为有__proto__原型的存在

我们打印这两个看看里面有什么

console.log(ldh)
console.dir(Star)

结果如下

我们可以看到ldh这个实例之中是有__proto__的,而构造函数也是有prototype的,那既然说__proto__指向构造函数的prototype对象,那么我们来看看是不是真的

console.log(ldh.__proto === Star.prototype)//true

结果自然是正确的

那既然实例的对象原型(ldh.proto)和构造函数的原型对象(Star.prototype)是一样的,那么我们就可以解释的通为什么实例可以直接使用构造函数上面的方法了

constructor构造函数

我们先打印一点东西看看

console.log(ldh.__proto__)
console.dir(Star.prototype)

结果如下


我们可以看到两个里面都有一个constructor对象,那么这个是什么玩意呢

其实这个我们还是称之为构造函数,因为它指向构造函数的本身,

我们可以试试看是不是这样

console.log(ldh.__proto__.constructor)

结果是和预期的一样的

所以constructor主要用于记录该对象引用于哪个构造函数,他可以让原型对象指向原来的构造函数

怎么用呢,可以看看这种情况

现在我们的构造函数有很多的方法,但是我们一直用.方法的形式好像有点麻烦,干脆就直接使用对象存储吧

function Star(age, name) {this.age = agethis.name = name
}
Star.prototype = {sing:function(){console.log("我会唱歌")},movie:function(){console.log("我会演电影")}
}
let ldh = new Star(35, "刘德华")
console.log(ldh.__proto__.constructor)

结果如下

好像指向的就不是原来Star这个构造函数了,这是怎么回事

原来,Star.prototype本身就是一个对象,你给Star.prototype赋值一个对象,那就会把原来prototype上面的对象给覆盖了,所以这个时候就可以使用constructor了

function Star(age, name) {this.age = agethis.name = name
}
Star.prototype = {constructon:Starsing:function(){console.log("我会唱歌")},movie:function(){console.log("我会演电影")}
}
let ldh = new Star(35, "刘德华")
console.log(ldh.__proto__.constructor)

只需要在Star.prototype里面重新指向这个构造函数就解决问题了

三者的关系

看了这么多,我们应该可以理解构造函数、实例、原型对象之间的关系了吧,只有理解了这些,才能更快的理解原型链的内容

我们可以只用一张图表示他们的关系

下面开始原型链的理解

原型链

直接看图先:

讲解一下图里面的内容

  1. 首先说好了的每一个实例都有__proto__,而这个就指向的是构造函数的对象原型,所以ldh.__proto__和Star.prototype是等价的,即ldh.proto`能够只会Star这个构造函数呢,本质上就是通过Star.prototype指回去的。
  2. 那么我们就会想到Star.prototype的__proto__指向的会是谁呢,一打印就能看的出指向的是Object.prototype,所以不用想也知道他的构造函数肯定是Object了
  3. 那Object.prototype还有没有__proto__,打印一看就知道是为null,所以我们知道原型的终点就是null

每个构造函数都有一个原型对象,原型对象都包含一个指向构造函数的指针,而实例都包含一个指向原型对象的内部指针。那么假如我们让原型对象等于另一个类型的实例,结果会怎样?显然,此时的原型对象将包含一个指向另一个原型的指针,相应地,另一个原型中也包含着一个指向另一个构造函数的指针。假如另一个原型又是另一个类型的实例,那么上述关系依然成立。如此层层递进,就构成了实例与原型的链条。这就是所谓的原型链的基本概念

了解了原型链,我们再来了解最后一个概念

js的成员查找机制

  1. 当访问一个对象的属性或者方法的时候,首先查找这个对象自身有没有这个属性
  2. 如果没有就去找他的原型,也就是__proto__指向的prototype原型对象
  3. 如果还没有就去查找原型对象的原型,即Object的原型对象
  4. 以此类推一直找到null为止

所以我们经常可以使用一些对象上面的方法就是因为如此

function Star(age, name) {this.age = agethis.name = name
}
Star.prototype.sing =function(){console.log("我会唱歌")
}
let ldh = new Star(35, "刘德华")
Object.prototype.sex="男"
console.log(ldh.sex)//男

这个是可以输出Object.prototype上面的sex属性的

我们还知道Object.prototype上面有一个toString方法,但是我们自己写的Star构造函数和ldh对象里面是都没有这个方法的,那么我们还可以使用这个方法吗

测试一下不就知道了

function Star(age, name) {this.age = agethis.name = name
}
Star.prototype.sing =function(){console.log("我会唱歌")
}
let ldh = new Star(35, "刘德华")
console.log(ldh.toString())//[object Object]

结果依然是正确的,所以这也验证了我们上面的规则

原型链的理解(全面)相关推荐

  1. 【Day03】使用原型最大的好处及原型链的理解

    面试题 使用原型最大的好处,原型链的理解 题解 原型优缺点简单分析 通过原型链继承的方式,原先存在父类型的实例中的所有属性和方法,现在也能存在于子类型的原型中了: 在通过原型链实现继承时,原型实际上会 ...

  2. JavaScript原型链的理解

    一.原型链的概念 JavaScript是一门面向对象的编程语言,JavaScript 中的所有事物都是对象,并且对象与对象之间不是彼此独立的,而是有"继承"关系的. 这种" ...

  3. JS原型、原型链深入理解

    原型是JavaScript中一个比较难理解的概念,原型相关的属性也比较多,对象有"prototype"属性,函数对象有"prototype"属性,原型对象有&q ...

  4. 原型链的理解_javascript之快速理解(原型链)

    希望通过比较通俗易懂的讲解和简短的文字,让大家能快速理解什么是原型链,如果有不对的地方也请各位大佬快速纠正,一起共勉,使我们初学者快速进阶! 话不多说,我们切入正题,按着我的步骤一步一步往下看,或许你 ...

  5. 【javascript】对原型对象、原型链的理解

    原型对象,原型链这些知识属于基础类知识.但是平时开发过程中也很少用到. 看网上的意思,原型链用于es5开发场景下的继承.es6有了类语法糖之后,就自带继承了. 通过理解,个人画了一张原型链解构的关系图 ...

  6. js原型和原型链_理解JS中的原型和原型链

    导读:JavaScript中(JS)的原型和原型链是web前端开发面试中经常被问到的问题:同时,如果我们能很好的理解JS中的原型和原型链,对于控制台输出的很多信息我们也能更好的理解,而原型链也是实现继 ...

  7. 对js原型和原型链的理解

    学习到 JavaScript 原型这个地方的时候,最开始是比较懵的状态,今天早上起来看了下红宝书中对于原型的解释,慢慢的也就有了些了解,但是解释的比较官方.接下来,我会把自己的理解分享下来,尽量用通俗 ...

  8. 原型和原型链的理解(Function,Object特例深入理解)

    原型我们可以分为显式原型和隐式原型. 显式原型: 每个函数都有一个prototype属性,即显式原型(属性),它默认指向一个object空对象(称为原型对象): 而原型对象中有一个属性construc ...

  9. JS 中原型和原型链深入理解

    作者: erdu segmentfault.com/a/1190000014717972 首先要搞明白几个概念: 函数(function) 函数对象(function object) 本地对象(nat ...

最新文章

  1. 速度快到飞起 如何跟蜻蜓的大脑学习计算?
  2. 中医点滴 1 --- 冬季外感喉咙痛 寒性荨麻疹
  3. 三:CAP与Base理论
  4. python飞机大战源代码-python版飞机大战代码分享
  5. 数字在数组中出现的次数
  6. 计算机软件及应用stata,蒙特卡洛模拟及其Stata应用实现
  7. java换水_java-交流灌水之谁是水王?
  8. Apple individual program 加入之后的玩法 官方资源
  9. 360手机卫士大数据驱动犯罪打击 配合警方破案成果显著
  10. dev c++代码自动补全_python3代码如何自动补全?
  11. mabatis传入参数
  12. 前后端分离状态下的工作与交互
  13. Python xlwt 操作 excel 表格基础(一):单元格写入、合并、插入位图等
  14. MATLAB绘制平方函数,MATLAB绘制由函数x^2/4+y^2/9+z^2/16=1形成的立体图,
  15. 群论基础速成(3):拉格朗日定理、直积与半直积
  16. 根据出生年月日计算出生了多少年,多少月,多少天
  17. 8.1 结构体的定义和使用
  18. 用Python写中文数字对照表
  19. 医学自然语言处理相关资源整理
  20. 量化投资学习——股指期货研究(四)

热门文章

  1. 让你脑洞大开的创新思维方法:水平思维
  2. 经典面试题:如何快速求解根号2?
  3. 择校倒计时:权威专家齐聚北京,解读最新国际学校招生政策
  4. 图像超分辨率SPSR:利用梯度信息来保持图像结构
  5. CMDB(配置管理数据库)基础知识详解
  6. 西雅图不相信爱情,66岁比尔盖茨离婚!财产分割成焦点
  7. 标准坐标系与火星坐标系(高德)百度坐标系之间互转
  8. Linux 修改文件夹和文件权限
  9. 第十四届蓝桥杯C/C++b组冶炼金属(C语言版二分做法)
  10. 轮廓系数sklearn.metrics.silhouette_score