1 、构造函数创建对象

我们先使用构造函数创建一个对象:

 function Person(){

 }
var p = new Person();
p.name = 'ccy';
console.log(p.name);//ccy

在这个例子中, Person 就是一个构造函数,我们使用 new 创建了一个实例对象 person 。
很简单吧,接下来进入正题:

2 、 prototype

每个函数都有一个 prototype 属性,就是我们经常在各种例子中看到的那个 prototype ,比如:

 function Person(){

 }
Person.prototype.age=18;
var p1 = new Person();
var p2 = new Person();
console.log(p1.age);//
console.log(p2.age);//

那这个函数的 prototype 属性到底指向的是什么呢?是这个函数的原型吗?
其实,函数的 prototype 属性指向了一个对象,这个对象正是调用该构造函数而创建的实例的原型 , 也就是
这个例子中的 person1 和 person2 的原型。
那么什么是原型呢?你可以这样理解:每一个 JavaScript 对象 (null 除外 ) 在创建的时候就会与之关联另一个
对象,这个对象就是我们所说的原型,每一个对象都会从原型 ” 继承 ” 属性。
让我们用一张图表示构造函数和实例原型之间的关系:

在这张图中我们用 Object.prototype 表示实例原型
那么我们该怎么表示实例与实例原型,也就是 person 和 Person.prototype 之间的关系呢,这时候我们就要
讲到第二个属性:

3 、 __proto__

这是每一个 JavaScript 对象 ( 除了 null) 都具有的一个属性,叫 __proto__ ,这个属性会指向该对象的原型。
为了证明这一点 , 我们可以在火狐或者谷歌中输入:

 function Person(){

 }
var p = new Person();
console.log(p.__proto__ === Person.prototype);//true

于是我们更新下关系图:

既然实例对象和构造函数都可以指向原型,那么原型是否有属性指向构造函数或者实例呢?

4 、 constructor

指向实例倒是没有,因为一个构造函数可以生成多个实例,但是原型指向构造函数倒是有的,这就要讲
到第三个属性: construcotr ,每个原型都有一个 constructor 属性指向关联的构造函数
为了验证这一点,我们可以尝试:

 function Person(){

 }
console.log(Person === Person.prototype.constructor);//true

所以再更新下关系图:

综上我们已经得出:

 function Person(){

 }
var person = new Person();
console.log(person.__proto__ === Person.prototype);//true
console.log(Person === Person.prototype.constructor);//true
//顺便学习ES5获取对象原型方法
console.log(Object.getPrototypeOf(person) === Person.prototype);//true

了解了构造函数、实例原型、和实例之间的关系,接下来我们讲讲实例和原型的关系:

5 、实例与原型

当读取实例的属性时,如果找不到,就会查找与对象关联的原型中的属性,如果还查不到,就去找原型
的原型,一直找到最顶层为止。
举个例子:

 function Person(){

 }
var person = new Person();
Person.prototype.name='hs';
person.name='ccy';
console.log(person.name);//ccy
delete person.name;
console.log(person.name);//hs

在这个例子中,我们设置了 person 的 name 属性,所以我们可以读取到为 ’name of this person’ ,当我们删除
了 person 的 name 属性时,读取 person.name ,从 person 中找不到就会从 person 的原型也就是 person.__proto__ ==
Person.prototype 中查找,幸运的是我们找到了为 ’name’ ,但是万一还没有找到呢?原型的原型又是什么呢?
在前面,我们已经讲了原型也是一个对象,既然是对象,我们就可以用最原始的方式创建它,那就是

 function Person(){

 }
var person = new Person();
Person.prototype.name='hs';
person.name='ccy';
console.log(person.name);//ccy
delete person.name;
console.log(person.name);//hs
Object.prototype.name='obj';
delete Person.prototype.name;
console.log(person.name);//obj

所以原型对象是通过 Object 构造函数生成的,结合之前所讲 , 实例的 __proto__ 指向构造函数的 prototype, 所

以我们再更新下关系图:

6 、原型链

那 Object.prototype 的原型呢?
null ,嗯,就是 null, 所以查到 Object.prototype 就可以停止查找了
所以最后一张关系图就是

顺便还要说一下,图中由相互关联的原型组成的链状结构就是原型链,也就是蓝色的这条线。

7 、补充

最后,补充和纠正本文中一些不严谨的地方:
首先是 constructor,

 function Person(){

 }
var person = new Person();
console.log(person.constructor === Person);//true

当获取 person.constructor 时,其实 person 中并没有 constructor 属性 , 当不能读取到 constructor 属性时,会从

person 的原型也就是 Person.prototype 中读取,正好原型中有该属性,所以

 console.log(person.constructor === Person.prototype.constructor);//true

其次是 __proto__, 绝大部分浏览器都支持这个非标准的方法访问原型,然而它并不存在与

Person.prototype 中,实际上,它是来自于 Object.prototype ,与其说是一个属性,不如说是一个 getter/setter ,
当使用 obj.__proto__ 时,可以理解成返回了 Object.getPrototypeOf(obj)
最后是关于继承,前面我们讲到 “ 每一个对象都会从原型 ” 继承 ” 属性 ”, 实际上,继承是一个十分具有迷惑
性的说法,引用《你不知道的 JavaScript 》中的话,就是 : 继承意味着复制操作,然而 JavaScript 默认并不会复
制对象的属性,相反, JavaScript 只是在两个对象之间创建一个关联,这样,一个对象就可以通过委托访问
另一个对象的属性和函数,所以与其叫继承,委托的说法反而更准确些。

原文来自路通牟垚同学~~~

最新文章

  1. UVALive 2453 Wall (凸包)
  2. HDU 5475(2015 ICPC上海站网络赛)--- An easy problem(线段树点修改)
  3. java中获取ServletContext常见方法
  4. IOS基础库
  5. 数据库的索引和填充因子fillfactor
  6. Seismic Unix的一些历史
  7. Delphi结构体数组指针的问题
  8. python【第二篇】列表、元组、字典及文件操作
  9. cf B. Fox Dividing Cheese
  10. PhotoShop-CS4使用-----如何对psd进行简单切图
  11. Hibernate框架--关联映射,一对多,多对多 inverse cascade
  12. Python教程(2.3)——运算符和类型转换
  13. spring cloud sidecar
  14. python之匿名函数以及在内置函数中的使用
  15. HDU 4764 Stone(巴什博奕)
  16. 解决Windows Server 2008R2通过计划任务定时执行bat文件,显示成功但实际未执行
  17. 关于EL表达式随笔记录
  18. asp.net mvc Htmlhelper简单扩展
  19. DedeCMS织梦文章页图片地址为绝对路径实现方法
  20. maven搭建ssh项目及遇到的问题

热门文章

  1. boost asio 学习(七) 网络基础 连接器和接收器(TCP示例)
  2. 2019.02.16 bzoj5466: [Noip2018]保卫王国(链分治+ddp)
  3. Linux 第十一天
  4. MFC在对话框中嵌入对话框
  5. Python语言中的按位运算
  6. MD5盐值加密
  7. 去掉input[type="number"]的默认样式
  8. Autofac与AOP功能例子
  9. redis知识点杂记
  10. [UWP] 用 AudioGraph 来增强 UWP 的音频处理能力