原型模式创建对象也有自己的缺点,它省略看构造函数传参初始化这一过程,带来的缺点就是初始化的值都是一致的。

而原型最大的缺点就是它优点,那就是共享。

原型中所有属性是被很多实例共享的,共享对于函数非常合适,对于包含基本值的属性也还可以,但如果属性包含引用类型。

就存在一定的问题:

	function Box(){};
Box.prototype={
Constructor:Box,
name:"link",
age:25,
family:['哥哥','弟弟','妹妹'],
run:function(){
return this.name+this.age+'运行中。。。'
}
}
var box1=new Box();
alert(box1.family)
box1.family.push('姐姐') //添加一个引用类型
alert(box1.family) // 输出 哥哥弟弟妹妹姐姐 var box2=new Box();
alert(box2.family) //共享了box1添加的引用类型的原型 // 输出 哥哥弟弟妹妹姐姐

ps:数据共享的缘故,导致很多开发者放弃使用原型,因为每次实例化出的数据需要保留自己的特性,而不能共享。

为了解决构造传参和共享问题,可以组合构造函数+原型模式

function Box(name,age){            //不共享的使用构造函数
this.name=name;
this.age=age;
this.family=['哥哥','弟弟','妹妹'];
}
Box.prototype={ //共享的使用原型模式
constructor:Box,
run:function(){
return this.name+this.age+'运行中。。。'
}
}
var box1=new Box('link',25);
box1.family.push('姐姐')
alert(box1.run())
alert(box1.family) // 输出 哥哥弟弟妹妹姐姐 var box2=new Box('links',25);
alert(box2.run())
alert(box2.family) // 输出 哥哥弟弟妹妹

ps:这种混合模式很好的解决了传参和引用共享的大难题。是创建对象比较好的方法。

 原型模式,不管你是否调用了原型中的共享方法,它都会初始化原型中的方法,并且在声明一个对象时,构造函数+原型部分很让人怪异,最好就是把构造函数和原型封装到一起。为了解决这个问题,我们可以使用动态原型模式。

	      //可以将原型封装到构造函数里面
function Box(name,age){
this.name=name;
this.age=age;
alert('初始化开始')
Box.prototype.run=function(){
return this.name+this.age+'运行中...'
}
alert('初始化结束')
}
//原型初始化,执行一次就行,没有必要每次都构造函数实例化的时候初始化!
var box1=new Box('link',53);
alert(box1.run()) var box2=new Box('that',5311);
alert(box2.run())

原型初始化,执行一次就行,没有必要每次都构造函数实例化的时候初始化!

          function Box(name,age){
this.name=name;
this.age=age; if(typeof this.run!='function'){ //查看this是否有run
alert('初始化开始')
Box.prototype.run=function(){
return this.name+this.age+'运行中...'
}
alert('初始化结束')
} }
//原型初始化,执行一次就行!
var box1=new Box('link',53);
alert(box1.run()) var box2=new Box('that',5311);
alert(box2.run())

ps:使用动态原型模式,要注意一下,就是不可以再使用字面量的方式重写原型,因为会切断实例和新原型之间的关联。

如果这几种方式不能满足需求,可以使用一开始那种模式:寄生构造函数!

	function Box(name,age){
var obj = new Object();
obj.name=name;
obj.age=age;
obj.run=function(){
return this.name+this.age+"运行中....."
}
return obj
}
var box1=new Box('link',53);
alert(box1.run())

ps:寄生构造函数,其实就是工厂模式+构造函数模式。这种模式比较通用,但是不能确定对象关系,所有,在可以使用之前所说的模式时,不建议使用此模式!

在什么情况下使用寄生构造函数比较合适呢?

假如要创建一个额外方法的引用类型。由于之前说明不建议直接使用String.porotype.addstring方法,

可以使用寄生构造的方式添加:

function mystring(string){
var str=new String(string);
str.addString=function(){
return this+',添加';
}
return str;
}
var box1=new mystring('link');
alert(box1.addString());

在一些安全的环境中,比如禁止使用this和new,这里的this是构造函数里不使用this,这里的new是在外部实例化构造函数时不使用new,

这种创建方式叫稳妥构造函数。

            function Box(name,age){
var obj = new Object();
obj.run=function(){
return name+age+"运行中....."
}
return obj
}
var box1=Box('link',53);
    alert(box1.run())

ps:稳妥构造函数和寄生类似。

Javascript面对对象. 第四篇的更多相关文章

  1. Javascript面对对象. 第五篇

    继承 继承是面向对象中一个核心的概念.其他正统面向对象语言都会用两种方式实现继承: 一个是接口实现,一个是继承. 而ECMAScript只支持继承,不支持接口实现,而实现继承的方式依靠原型链完成. / ...

  2. Javascript面对对象. 第三篇

    3.字面量 为了让属性和方法很好的体现封装的效果,并且减少不必要的输入原型的创建可以使用字面量. function Box(){} //使用字面量的方法创建原型对象,这里的{}就是对象,是Object ...

  3. 深入理解javascript作用域系列第四篇——块作用域

    × 目录 [1]let [2]const [3]try 前面的话 尽管函数作用域是最常见的作用域单元,也是现行大多数javascript最普遍的设计方法,但其他类型的作用域单元也是存在的,并且通过使用 ...

  4. 深入理解javascript作用域系列第四篇

    前面的话 尽管函数作用域是最常见的作用域单元,也是现行大多数javascript最普遍的设计方法,但其他类型的作用域单元也是存在的,并且通过使用其他类型的作用域单元甚至可以实现维护起来更加优秀.简洁的 ...

  5. Javascript面对对象. 第一篇

    Javascript,有两个种开发模式: 1.函数式(过程化)2.面对对象(oop),面对对象语言有一个标志,就是类,而通过类可以创建任何多个属性和方法,而Ecmascript没有类的概念,因此它的对 ...

  6. Javascript面对对象. 第二篇

    但是还有一个问题,就是识别的问题,因为根本无法搞清楚他们到底是哪个对象的实例. 1.构造函数 function CreateObject(name,age){ //创建一个对象,使用构造函数的对象都是 ...

  7. javascript面对对象编程 之继承

    上一篇博客中为大家介绍了javascript面向对象编程原则的封装,今天为大家介绍继承.在javascript中没有类的概念,全部不能像c#.java语言那样.直接的用类去继承类.比方如今有比方.如今 ...

  8. javascript面向对象系列第四篇——选项卡的实现

    前面的话 面向对象的应用并非只是读几本书那么容易,需要有大量的工程实践做基础才能真正理解并学会使用它.本文将用面向对象的技术来制作一个简单的选项卡 图示说明 由图示结果看到,这是一个非常简单的选项卡. ...

  9. 深入理解javascript函数系列第四篇——ES6函数扩展

    × 目录 [1]参数默认值 [2]rest参数 [3]扩展运算符[4]箭头函数 前面的话 ES6标准关于函数扩展部分,主要涉及以下四个方面:参数默认值.rest参数.扩展运算符和箭头函数 参数默认值 ...

随机推荐

  1. EntityFrameWork分页

    EF分页代码 using System; using System.Collections.Generic; using System.Linq; using System.Web; using Sy ...

  2. Python科学计算之Pandas

    Reference: http://mp.weixin.qq.com/s?src=3&timestamp=1474979163&ver=1&signature=wnZn1UtW ...

  3. Mongodb 导出json 和csv 格式数据

    导出到json: $ mongoexport.exe  -d TestDB -c TestCollection -o  ./test.json 导出到csv: If you want to outpu ...

  4. Linux之目录基本操作命令

    Linux之目录基本操作命令 目录基本操作命令 1.tree命令 tree命令以树状图列出目录的内容. 语法 tree(选项)(参数) 选项 1.-a显示所有文件和目录 2.-A使用ASNI绘图字符显 ...

  5. pageX,clientX,offsetX,layerX的那些事

    在各个浏览器的JS中,有很多个让你十分囧的属性,由于各大厂商对标准的解释和执行不一样,导致十分混乱,也让我们这些前端攻城狮十分无语和纠结>_< John Resig大神说过,动态元素有3个 ...

  6. 最简化模型2——css3分阶段动画效果(经过实测)之转动的div

    @keyframes mymove{    0%{top: 0;left: 0;transform:rotate(50deg);}    10%{top: 100px;left: 50px;trans ...

  7. js原生:封装document.getElementByClassName()函数

    //接口封装:封装document.getElementByClassName()函数function getElementsByClassName (cName,domTag,root) {//该函 ...

  8. C-Sharp网络编程案例解析(Socket类的使用)

    Server端: using System; using System.Collections.Generic; using System.Text; using System.Net; using ...

  9. Backbone源码解读(一)事件模块

    Backbone源码浅读: 前言: Backbone是早起的js前端MV*框架之一,是一个依赖于underscore和jquery的轻量级框架,虽然underscore中基于字符串拼接的模板引擎相比如 ...

  10. 大数据时代的杀手锏----Tachyon

    一.Tachyon系统的简介 Tachyon是一个分布式内存文件系统,可以在集群里以访问内存的速度来访问存在tachyon里的文件.把 Tachyon是架构在最底层的分布式文件存储和上层的各种计算框架 ...