在大多数面向对象语言中,对象总是由类中实例化而来,类和对象的关系就像模具跟模件一样。Javascript中没有类的概念,就算ES6中引入的class也不过是一种语法糖,本质上还是利用原型实现。在原型编程语言中,类并不是必需的,对象不一定需要由类实例化而来,而是通过克隆另外一个对象来得到。

  原型模式是用来创建对象的一种模式。在以类为中心的语言中,要创建一个对象首先要指定这个对象的类型,然后实例化一个对象。使用原型模式创建对象时不必关心对象的具体类型,而是找到一个对象,然后通过克隆来创建一个一模一样的对象。所以在前者中如果要根据一个对象创建多个相同的对象,我们需要先保存这个对象的所有属性信息,然后将属性信息设置到新创建的对象上,而在原型模式中我们只需要使用克隆就能完成同样的功能。

  在某些玄幻小说中经常会出现某些修真大能,以分身的形式游走世间。这个过程很适合原型模式的应用:

function Master(){
this.blood = 100;
this.level = 6;
} var noumenon = new Master();
noumenon.level = 9; var ektype = Object.create(noumenon); console.log(ektype);

  ES5提供了原生的克隆方法:Object.create,不支持这个方法的浏览器可以使用如下代码:

function clone(obj){
function F(){};
F.prototype = obj;
return new F();
} var ektype = clone(noumenon);

  通过以上代码,我们看到了如何通过原型模式来克隆出一个一模一样的的对象。原型模式的真正意义并非创建一个一模一样的对象,而是提供一种创建对象的方式,Javascript的面向对象机制是基于原型模式的,他的对象系统就是使用原型模式,通过克隆来创建的,克隆是创建一个对象的过程和手段。以继承为例:

function Person(name){
this.name = name;
} function Developer(lang){
this.language = lang;
} var p = new Person('coder'); Developer.prototype = p; var dev = new Developer('Javascript');

  基于原型的继承体系,子类的每次实例化都是对其构造函数的prototype属性的克隆。所以每次创建Developer对象,其实都是在对p对象的克隆。

  在Java等以类为中心的面向对象语言中,经常使用new实例化一个对象。但是Javascript是基于原型的面向对象语言,在这里new运算符创建对象的方式与Java中的new运算符并不相同,Javascript中的new运算符也是通过克隆来实例化对象的,克隆的是构造器函数的原型对象,new运算符的作用等同于如下代码:

function Person(name){
this.name = name;
} function Developer(lang){
this.language = lang;
} var p = new Person('coder'); Developer.prototype = p; function _new(_Constructor) {
var that = Object.create(_Constructor.prototype);
var args = Array.prototype.slice.call(arguments, 1);
var other = _Constructor.apply(that, args); return (typeof other === 'object' && other) ? other : that;
}
_new(Developer, 'JavaScript')

  从这我们也可以看出,Javascript的原型实际上存在着诸多矛盾,它的某些复杂语法看起来就像那些基于类的语言,这掩盖了它的原型机制。所以jQuery中尽量避免使用new运算符来创建对象。

  根据前面所说Javascript中新创建的对象都是基于原有对象的克隆,所以在Javascript中存在一个最原始的对象:Object.prototype,所有对象都是由它克隆而来。

  这里所说的克隆是在Javascript原型模式这一大环境下的一种语义表达,在计算机的物理世界中并不存在真正的克隆。所以这里对于克隆应当理解为产生一个拥有__proto__属性指向原对象的对象的过程,原对象成为被克隆的对象,也就是构造函数的prototype对象。

  拥有以上共识后,我们可以得到在Javascript中原型编程的基本规则:

  1. Javascript中绝大多数数据都是对象
  2. 要得到一个对象,不是通过实例化类,而是找到一个对象作为原型并克隆它
  3. 对象会记住它的原型
  4. 如果对象无法响应某个请求,他会把这个请求委托给它自己的原型

参考书籍:

《Javascript语言精粹》

《Javascript设计模式与开发实践》

Javascript原型模式总结梳理的更多相关文章

  1. 面向对象的JavaScript --- 原型模式和基于原型继承的JavaScript对象系统

    面向对象的JavaScript --- 原型模式和基于原型继承的JavaScript对象系统 原型模式和基于原型继承的JavaScript对象系统 在 Brendan Eich 为 JavaScrip ...

  2. JavaScript原型模式

    一.提到原型模式,和构造函数关系密切,先讲一下它 javascript没有类,通过函数来模拟实现类,用new来创建对象,函数内部的this指针来指向调用它的对象. 事例中创建对象myGril,这个对象 ...

  3. Javascript:原型模式类继承

    原型模式 每个函数(准确说不是类.对象)都有一个prototype属性,这个属性是一个指针,指向一个对象. 使用原型对象的好处是可以让所有对象实例共享它包含的属性和方法.   1.原型对象 (1)当创 ...

  4. javascript原型模式理解

    传统的面向对象语言中,创建一个对象是通过使用类来创建一个对象的,比如通过类飞行器来创建一个对象,飞机. 而js这种没有类概念的动态设计语言中,创建对象是通过函数来创建的,所以通常也把js称为函数式语言 ...

  5. JavaScript原型模式-理解对象

    一:简述 当初学编程一看到什么什么模式就比较头晕,不过本文我们通过简单的示例代码来说一下js 对象这个话题 ,来看下如何理解这个原型模式. 二:理解对象 1.简单对象 js对象中没有java.C#等类 ...

  6. JavaScript原型模式(prototype)

    1.原型是一个对象,其他对象可以通过它实现属性的继承所有对象在默认的情况下都有一个原型,因为原型的本身也是对象,所以一个类的真正原型是被类的内部[prototype]属性所指出.每个函数都有一个属性叫 ...

  7. JavaScript设计模式-3.原型模式

    <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title> ...

  8. 初涉JavaScript模式 (7) : 原型模式 【三】

    组合使用构造函数模式和原型模式 上篇,我们提到了原型模式的缺点,就是每个实例不能拥有自己的属性,因为纯原型模式所有的属性都是公开给每个实例的,故我们可以组合使用构造函数模式和原型模式.构造函数用来定义 ...

  9. [设计模式] JavaScript 之 原型模式 : Object.create 与 prototype

    原型模式说明 说明:使用原型实例来 拷贝 创建新的可定制的对象:新建的对象,不需要知道原对象创建的具体过程: 过程:Prototype => new ProtoExam => clone ...

随机推荐

  1. Linux C++ 开发常用工具,常用指令工作手册

    vim常用: :set nu显示行数 :set mouse=a 鼠标滑动屏幕,:set ic :set noic 忽略不忽略大小写 /word_to_search\c \c表示忽略大小写 c小写忽略, ...

  2. Jmeter学习

    网址: http://www.ltesting.net/ceshi/open/kyxncsgj/jmeter/ http://www.cnblogs.com/TankXiao/p/4059378.ht ...

  3. C#实现:给定任意要给字符串,输出所有可能的回文的子字符串集合。

    class Program { static void Main(string[] args) { string testStr = "sdfadfdsfadfdsfsdf"; i ...

  4. VS与ultraedit 正则表达式替换

    ASP中把request("{param}")调用替换为requestX("{param}") VS 表达式替换(?<a>request\(&quo ...

  5. Xamarin +vs2015 Android 开发GPS loaction 返回 null 小结

    最近公司要开发android 所以研究了一下Xamarin  to android 中个GPS 废话不多说,说重点. 想获取手机上的gps信息必不可少的就是要使用 LocationManager Lo ...

  6. Mvc分页扩展类 分页代码 带跳转

    public static class HtmlPager { public static MvcHtmlString MvcPager(this HtmlHelper html, string cu ...

  7. Qt 如何判断文件是不是一个目录

    做个文件管理系统的时候碰到的question,下面来讲解下方法,因为在网上都没找到,就只能翻官方文档相关信息结果找到isFile(),isDir(); 因为是文件管理系统,那么肯定现先获取到它的路径以 ...

  8. 字符串流stringstream(头文件sstream)

    今天看到一样很有趣的东西,可以用于各种类型的转换.其实一个文本可以看作一个长长的字符串,整数啊浮点数的都是字符串,于是在字符串流里面就可以很方便地玩转各种类型,比如说: #include<ios ...

  9. C#自旋的艺术

    CODE1: while (status == ServerStatus.Started) { if (*TaskLocker > 0) { for (int i = 0; i != *Leve ...

  10. angularjs 1.x $q模块使用

    什么是$q $q是angularjs1.x中内置服务,在需要使用时可以注入它. angular.module('app').controller('myController', function my ...