创建一个对象,先来看一段代码:

// 例如创建一个 Person 的构造函数, 让人有名字, 可以说话
function Person ( name ) {
this.name = name;
// 可以说话, 需要有一个方法
this.sayHello = function () {
console.log( '你好, 我是 ' + this.name );
};
}
var p1 = new Person( '小明' );
var p2 = new Person( '大伟' );
console.log( p1.sayHello == p2.sayHello ); // false

  说明p1的sayHello()方法 和 p2的sayHello()方法 不相同。也就间接的说明每次创建一个实例化对象的时候都会在内存中重新开辟一个存储空间进行创建,一旦频繁创建实例化的对象时,会造成内存资源的浪费 。

 解决方法
          将公共的方法提取出来进行函数封装 (缺点: 代码比较乱、命名冲突几率大)
          将所有方法都绑定到对象的属性上(虽然 提高了代码可读性、也减少了命名冲突,貌似还是可以进行优化)
          JS 原生就支持解决方法:
             每个函数都有一个 prototype(原型)属性,将共享的方法绑定到 .prototype 原型上 即可
// 例如创建一个 Person 的构造函数, 让人有名字, 可以说话
function Person ( name ) {
this.name = name;
// 可以说话, 需要有一个方法
this.prototype.sayHello = function () {
console.log( '你好, 我是 ' + this.name );
};
}
var p1 = new Person( '小明' );
var p2 = new Person( '大伟' );
console.log( p1.sayHello == p2.sayHello ); // true   说明p1与p2访问的是同一组属性,同一个sayHello()方法。间接的说明用原型绑定公共的方法(共用一个存储空间)



原型的使用   
constructor(构造器):每个构造函数被创建出来都有一个prototype(原型)属性,每个原型属性都有个constructor属性,该属性默认指向 原构造函数。
  // 首先需要构造函数, 原则就是将独有的方法放在 对象中
function Person ( name, age, gender ) {
this.name = name;
this.age = age;
this.gender = gender;
}
 
将共享的方法放到默认的 .prototype 原型中,而独有的数据与行为放到对象中
 
    // 将共享的方法提取出来
Person.prototype.sayHello = function () {
console.log( '你好, 我是 ' + this.name );
};
Person.prototype.eat = function () {
console.log( this.name + '在吃饭' );
}; Person.prototype.run = function () {
console.log( this.name + '在跑步. 已经跑了 ' + this.age + ' 年' );
}; // 直接给原型对象添加成员
var p1 = new Person( 'lilei', 19, '男' );
var p2 = new Person( 'hanmeimei', 18, '女' );
  给原型 .prototype属性 重新赋值 ,将原来默认的 .prototype 覆盖掉  
// 让 Person.prototype 指向另一个对象. 直接赋值
Person.prototype = { constructor: Person, //constructor 默认指向 Object ,将其改为指向 原构造函数 sayHello: function () {
console.log( '第二种做法: 你好, 我是 ' + this.name );
}, eat: function () {
console.log( '第二种做法: ' + this.name + ' 在吃饭' );
}, run: function () {
console.log( '第二种做法: ' + this.name + ' 在跑步. 已经跑了 ' + this.age + ' 年' );
}
}; var p1 = new Person( 'lilei', 19, '男' );
var p2 = new Person( 'hanmeimei', 18, '女' );
 
  如果访问的对象的某个方法时,实例化的对象上没有该方法,就会到该对象的原型 . prototype 上去找
 
   下面是一个简单的 原型结构 分析图:

          

          构造函数   ----------  使用 prototype 属性   -----  访问原型
          实例对象   ----------  使用 __proto__属性   -----  访问原型   
          针对构造函数而言,原型就是 构造函数的 prototype 属性 ---  原型属性
          针对实例对象而言,原型就是 实例对象的 __ptoto__属性 ---  原型对象 
 
  注:以上是个人对原型的理解及总结,如有笔误的地方还请大家多指教!

JS --- 原型模式的更多相关文章

  1. Js原型模式

    function Person(){ } Person.prototype.name = "xd"; Person.prototype.age = 26; Person.proto ...

  2. js原型模式和继承

    function SuperType() { this.property = true; //原型属性 } //基类方法 SuperType.prototype.getSuperValue = fun ...

  3. JS中prototype属性-JS原型模式

    /* *对象方法 *类方法 * 原型方法 */ function People(name) { this.name = name; this.say = function () { //对象方法 al ...

  4. JS 原型模式创建对象

    例子: class Test { constructor(val) { this.val = val } walk() { console.log(this) console.log('walk') ...

  5. js设计模式:工厂模式、构造函数模式、原型模式、混合模式

    一.js面向对象程序 var o1 = new Object();     o1.name = "宾宾";     o1.sex = "男";     o1.a ...

  6. 面向对象JS基础讲解,工厂模式、构造函数模式、原型模式、混合模式、动态原型模式

    什么是面向对象?面向对象是一种思想!(废话). 面向对象可以把程序中的关键模块都视为对象,而模块拥有属性及方法.这样我们如果把一些属性及方法封装起来,日后使用将非常方便,也可以避免繁琐重复的工作.接下 ...

  7. 关于js的对象创建方法(简单工厂模式,构造函数模式,原型模式,混合模式,动态模式)

    // 1.工厂方式创建对象:面向对象中的封装函数(内置对象) 简单来说就是封装后的代码,简单的工厂模式是很好理解的,关于它的作用,就是利用面向对象的方法,把一些对象封装,使一些占用空间多的,重复的代码 ...

  8. JS面向对象基础讲解(工厂模式、构造函数模式、原型模式、混合模式、动态原型模式)

    什么是面向对象?面向对象是一种思想. 面向对象可以把程序中的关键模块都视为对象, 而模块拥有属性及方法. 这样如果我们把一些属性及方法封装起来,日后使用将非常方便,也可以避免繁琐重复的工作.   工厂 ...

  9. JS面向对象(1)——构造函数模式和原型模式

    1.构造函数模式 构造函数用来创建特定的类型的对象.如下所示: function Person(name,age,job){ this.name=name; this.job=job; this.ag ...

随机推荐

  1. cs

    cs <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.o ...

  2. ios 证书申请和发布流程

    证书是什么? 上面这个就是我们申请好证书后,下载到本地的.cer文件,也就是常说的开发证书与发布证书的样式.这.cer文件格式的证书是让开发者使用的设备(也就是你的Mac)有真机调试,发布APP的权限 ...

  3. (转)HTTP 长连接和短连接

    1. HTTP协议与TCP/IP协议的关系 HTTP的长连接和短连接本质上是TCP长连接和短连接.HTTP属于应用层协议,在传输层使用TCP协议,在网络层使用IP协议.IP协议主要解决网络路由和寻址问 ...

  4. 点餐系统3个sprint的团队贡献分

    第一次冲刺贡献分   团员名字 贡献分 麦锦俊 18分 冯婉莹 21分 李康梅 19分 张鑫相 20分 曹嘉琪 22分     第二次冲刺贡献分   团员名字 贡献分 麦锦俊 19分 冯婉莹 20分 ...

  5. MFC Picture控件加载图片

    CStatic *pPic = (CStatic*)GetDlgItem(IDC_PICTURE); CBitmap bitmap; bitmap.LoadBitmapW(IDB_BITMAP2); ...

  6. ADT(Android Developer Tools) GIT功能不全,远程提交的时候账户密码不能保存账户和密码解决方式

    需要安装Eclipse的GIT插件EGIT http://download.eclipse.org/egit/updates/

  7. 写了placement new就要写placement delete

    "placement new"通常是专指指定了位置的new(std::size_t size, void *mem),用于vector申请capacity剩余的可用内存. 但广义的 ...

  8. C/C++之指针加减法

    C和C++中可对指针进行加减,但对其进行乘除则基本无实际意义.一般来说,对指针进行减法的前提是减数和被减数均指向同一数组.加法同理.需要注意的是,两个指针的减法,结果是两个地址之间索引变量的数目,而不 ...

  9. 此操作失败的原因是对 IID 为“{000208DA-0000-0000-C000-000000000046}”的接口的 COM 组件调用 QueryInterface

    有些电脑报错,有些电脑正常. 环境:VS2010 WinForm程序, Office2007 C#操作Excel时报错.错误: 无法将类型为“System.__ComObject”的 COM 对象强制 ...

  10. linux 中压缩记得压缩用c,解压用x

    tar -c: 建立压缩档案-x:解压-t:查看内容-r:向压缩归档文件末尾追加文件-u:更新原压缩包中的文件 这五个是独立的命令,压缩解压都要用到其中一个,可以和别的命令连用但只能用其中一个.下面的 ...