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

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

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

就存在一定的问题:

	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. ubuntu10.4的更新源因过期无法更新的解决方法

    转载自:http://blog.csdn.net/suquan629/article/details/52333769 ubuntu10.4到2016年早已停止了更新支持,ubuntu也不再维护了.官 ...

  2. UVA - 129 Krypton Factor (困难的串)(回溯法)

    题意:求由字母表前L个字母组成的字典序第n小的困难串.(如果一个字符串包含两个相邻的重复子串,则称它是"容易的串",其他串称为"困难的串".) 分析:回溯时,检 ...

  3. Github上的600多个iOS开源类库

    Github上的600多个iOS开源类库,入下图所示,里面有很多资源,学习积累的好资源 地址:http://github.ibireme.com/github/list/ios/

  4. 长平狐 Cocos2d-x 的“HelloWorld” 深入分析

                              Cocos2d-x 的“HelloWorld” 深入分析 本节所用Cocos2d-x版本:cocos2d-1.0.1-x-0.12.0 不能免俗,一 ...

  5. UVa 10551 - Basic Remains

    题目大意:关于大数的mod和进制转换,直接使用Java的BigInteger类,正在copy式学习中... import java.io.*; import java.util.*; import j ...

  6. 用python实现模拟登录人人网

    用python实现模拟登录人人网 字数4068 阅读1762 评论19 喜欢46 我决定从头说起.懂的人可以快速略过前面理论看最后几张图. web基础知识 从OSI参考模型(从低到高:物理层,数据链路 ...

  7. iOS 之 网络 NSURLSession

    NSURLSession相比NSURLConnection功能更强大,是更上层的网络封装.相比而言,普通应用场景下NSURLSession没有什么优势,但是,在程序切换到后台的情况下,NSURLSes ...

  8. 【腾讯优测干货分享】微信小程序之自动化亲密接触

    本文来自于腾讯优测公众号(wxutest),未经作者同意,请勿转载,原文地址:http://mp.weixin.qq.com/s/HcPakz5CV1SHnu-U8n85pw 导语 山雨欲来风满楼,最 ...

  9. oralce

    1.对数据库SQL2005.ORACLE熟悉吗?   SQL2005是微软公司的数据库产品.是一个RDBMS数据库,一般应用在一些中型数据库的应用,不能跨平台.   ORACLE是ORACLE公司的数 ...

  10. Spring框架中整合JUnit单元测试的方法

    一. 步骤: 1. 拷贝jar包: 1. JUnit-4.9.jar和spring-test-4.2.4.RELEASE.jar ; 2. 替换原来的main函数: 1. 在测试类上使用注解方式替换: ...