对JavaScript中原型模式的理解

一:什么是原型对象?有什么优点?

   简单的来说,无论何时,我们创建的每一个函数都有一个prototype属性,这个属性是一个指针,指向一个对象,这个对象包含了通过调用该构造函数所创建的对象共享的属性和方法。其实我们平常的叫法就是指:prototype就是通过该构造函数创建的某个实例的原型对象,但是其实prototype是每个构造函数的属性而已,只能说万物皆对象罢了。
   原型对象的优点是:所有的对象实例都可以共享它包含的属性和方法。这一点可以在构造函数里就可以看出来,因为构造函数在函数里面就定义了对象的实例信息,而原型对象可以在任何地方定义属性和方法。例如:

function Person(){}
Person.prototype.name = 'bangbang';
Person.prototype.age = 18;
Person.prototype.job = 'programmer';
Person.prototype.dream = function(){console.log('Change yourself');
}var person1 = new Person();
person1.dream();    //Change yourselfvar person2 = new Person();
person2.dream();
//判断两个实例继承的方法和属性是否全等
console.log(person1.dream === person2.dream);
console.log(person1.age === person2.age);

由以上的代码可以看出它比构造函数方法的好处就是,person1和person2访问的都是同一个dream()函数,即他们的属性和方法都是共享的。

二:深入理解原型对象和prototype?

  由上面可知,我们创建了一个函数,就会根据ECMAscript特定的规则为该函数创建一个prototype属性,这个属性指向函数的原型对象。在默认情况下,所有原型对象都会自动获得一个constructor(构造函数)属性,这个属性是一个指向prototype属性所在函数的指针。就像前面的例子,Person.prototype.constructor指向Person,而通过这个构造函数,我们还可以继续为原型对象添加其他属性和方法。
  下面,我们就开始从原理上说明上面代码运行机制的:

  1. 创建一个自定义的构造函数后,它的原型对象默认只会有constructor属性,其他属性和方法都是从Object继承而来的;
  2. 当调用构造函数创建一个新实例后,该实例的内部将包含一个指针,指向构造函数的原型对象。ECMA5中称这个指针叫[[prototype]]。虽然在脚本中没有标准的方式访问[[prototype]],但Firefox、Safari和Chrome在每个对象上都支持一个属性_proto_;而在其他浏览器中,这个属性则是完全不可见的。不过要明确的真正一点就是,这个连接存在于 实例构造函数的原型对象 之间,而不是存在于实例和构造函数之间,用前面使用Person构造函数和Person.prototype创建实例的代码为例,各个对象之间的关系如下图所示:

    上图展示了Person构造函数、Person的原型以及Person现有的两个实例之间的关系,再次,Person.prototype指向了原型对象,而Person.prototype.constructor又指回了Person。原型对象中除了包含constructor属性之外,还包括后来添加的其他属性。Person的每个实例——person1和person2都包含一个内部属性,该属性指向了Person.prototype;换句话说,他们与构造函数没有直接关系。
      注意:虽然这两个实例都不包含属性和方法,但我们却可以调用name、age、job、dream()方法和属性,这是通过查找对象属性的过程来实现的。
      虽然我们不能访问到[[prototype]],但可以通过isPrototypeOf()方法来确定对象之间是否存在这种关系。因为这两个实例都有一个指向Person.prototype的指针,因此,都返回true如下所示:
console.log(Person.prototype.isPrototypeOf(person1));//true
console.log(Person.prototype.isPrototypeOf(person2));//true

ECMA5增加了一个方法,叫Object.getPrototypeOf(),这个方法返回[[Prototype]]的值,也就是括号里面对象的原型,例如:

console.log(Object.getPrototypeOf(person1) == Person.prototype; // true
console.log(Object.getPrototypeOf(person1).name); //'bangbang'

用hasOwnProperty()方法可以检测一个属性是存在于实例中还是原型中。还是上面的例子:

console.log(person1.hasOwnProperty('name'); //false
person1.name = 'qiqi';
console.log(person1.hasOwnProperty('name'); //true —— 来自实例
console.log(person1.name);  //'qiqi' ——来自实例
delete person1.name;
console.log(person1.name); //'bangbang' —— 来自原型
console.log(person1.hasOwnProperty('name'); //true ——来自原型

当我们为person1添加name属性的时候,如下图图所示:

三:组合使用构造函数模式和原型模式优点最多:

  以上我讲述了用构造函数生成对象的原理以及生成的对象和原型对象之间的关系,原理了解了这么多,我么当然需要知道怎么在合适的时候用他们。创建自定义类型的最常见方式就是组合使用构造函数模式和原型模式。构造函数模式用于定义实例属性,而原型模式用于定义方法和共享的属性。每个实例都会有自己的一份实例属性的副本,但同时又共享着对方发的引用,最大限度的节省了内存。如下例所示:

     function Person(name,age,job){this.name = name;this.age = age;this.job = job;this.love = ['qiqi','lili'];}Person.prototype = {constructor : Person,dream : function(){console.log(this.love[0]);}}var person1 = new Person('bangbang',18,'programmer');var person2 = new Person('xiaoya',18,'teacher');console.log(person1.love);console.log(person2.love)console.log(person1.love === person2.love);  //false//给person1的love属性添加元素person1.love.push('niuniu');console.log(person1.love)  //["qiqi", "lili", "niuniu"]console.log(person2.love)  //["qiqi", "lili"]console.log(person1.love === person2.love);  //falseconsole.log(person1.dream === person2.dream);//true

以上这种模式是ECMAscript中使用最广泛的,认同度最高的,优点最多的创建自定义类型的方法,也就是创建JavaScript中类的方法。

深入理解prototype(原型对象)相关推荐

  1. 理解js的prototype原型对象

    我们创建的每一个函数都有一个prototype(原型)属性.这个属性是一个指针,指向一个对象,而这个对象的用途是包括能够由特定类型的全部实例共享的属性和方法.假设依照字面意思来理解,那么prototy ...

  2. 关于JavaScript的Prototype及原型对象的理解

    学习JavaScript时,就一定会涉及到两个概念–prototype,原型对象.自己在做项目时可能无意中使用到,但是却没有真正去了解这个东西,在学会使用的基础上,进一步去理解它会帮助自己吸收到更多不 ...

  3. 【JavaScript】JavaScript模拟实现面向对象一张图帮助你深刻理解原型链和原型对象

    文章目录 一.JavaScript模拟面向对象 1.函数是类 2.函数中各种变量的声明 3.关于函数内的this 小结:JavaScript中函数是什么? 4.练习:面向对象思想编写Complex类 ...

  4. prototype是原型对象,那__proto__又是什么呢,总不能是别名吧?

    做过前端的都知道,两个必会的知识就是原型和原型链,如果有人问你,原型是什么?你是不是回答对象中都有一个默认的属性叫prototype,指向的就是原型.如果再追问你,那原型链是什么呢?你是不是回答如果在 ...

  5. JavaScript 面向对象 (prototype 原型模式)

    一. JavaScript 设计思想 1994年,网景公司(Netscape)发布了Navigator浏览器0.9版.这是历史上第一个比较成熟的网络浏览器,轰动一时.但是,这个版本的浏览器只能用来浏览 ...

  6. 深入理解javascript原型和原型链

    文章目录 构造函数 1. new一个新对象的过程,发生了什么? 2. 手写new函数 3. 构造函数上的方法 原型 1. 什么是原型? 2. 原型的作用是什么? 3. 原型中this的指向是什么? 函 ...

  7. 初学JavaScript:js中的对象(对象+原型对象)

    文章目录 js对象详解 1.创建对象 字面量模式创建对象 构造函数模式创建对象 2.访问对象 访问属性 访问方法 3.遍历对象中的属性和属性值 4.往对象中新添属性 5.删除对象中的属性 6.Obje ...

  8. 构造函数、实例、原型对象、继承

    一.构造函数与原型对象之间的关系: 有一个Star构造函数,每一个构造函数里面都有一个原型对象,是通过构造函数的prototype指向这个原型对象的 同样在这个原型对象里面也有一个属性叫constru ...

  9. js 高级 原型对象

    原型链 任何对象都有原型对象,也就是prototype属性,任何原型对象也是一个对象,该对象就有__proto__属性,这样一层一层往上找,就形成了一条链,我们称此为原型链; 函数类,实例和原型对象三 ...

最新文章

  1. 简单ThreadPool实现
  2. ABAP取字符串中的连续数字
  3. Python matplotlib 和PIL
  4. python贪吃蛇小游戏_python开发贪吃蛇小游戏
  5. FreeSql (二十九)Lambda 表达式
  6. html把图片定位在盒子中心,html – CSS在图像的右上角定位一个图标
  7. 速成pytorch学习——2天
  8. 驱动模块的安装与卸载指令
  9. 何谓dB、dBm、dBi
  10. Java开发基础知识学习总结之(上)-王者笔记建议收藏
  11. EXCEL学习笔记----EXCEL操作
  12. 百度文件下载慢怎么办?~教你百度网盘无需VIP离线下载大文件
  13. AtCoder Beginner Contest 171 D - Replacing
  14. h5移动端生成海报,图文结合
  15. C语言中将字符数字转换为数值的小技巧和方法
  16. Activiti 从入门到精通
  17. 制作excle报盘模板
  18. 史上最全Hashmap面试总结,51道附带答案,持续更新中...
  19. java程序设计案例_Java程序设计案例教程
  20. JS判断某年某月有多少天

热门文章

  1. OpenCV之分水岭算法
  2. Unity三屏全屏方法
  3. Android:RecyclerView自动跳到顶部
  4. 江城子·西城杨柳弄春柔
  5. VScode输入 !无法自动生成html模板问题
  6. matlab算例并行教程,Matlab并行编程方法
  7. 智能千面模板最新带货骗局
  8. 未来十年是计算机,在未来的十年里计算机的作用有多大?
  9. 解决: ERR! network request to https://registry.npmjs.org/@fortawesome%2fvue-fontawesome failed 问题
  10. “网络游戏防沉迷系统”我本科的毕业设计