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

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

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

就存在一定的问题:

	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. 74HC166与TPIC6A595分析(转)

    源:Atmega162串行外设接口SPI 一.Atmega162的SPI接口基本概念与工作原理 SPI接口的全称是"Serial Peripheral Interface",意为串 ...

  2. 博客停更及OI退役公告

    停更&&OI退役 公告 高中OI之路就这样结束了,曾经想过回在NOI跪,APIO跪,HNOI跪却从未想过会在NOIP跪! 没办法自己作死啊,CCF感觉还是很良心的混个省一回来了,看以后 ...

  3. jenkins 构建时,取消构建测试类

    如图 点击配置,添加clean install  -Dmaven.test.skip=true 保存即可

  4. sqlserver merge into

    create table #ttt(id int,name nvarchar(10));merge into #ttt t using (select 1 as id ,'eee' as name ) ...

  5. [Angular Tutorial] 7-XHRs & Dependency Injection

    我们受够了在应用中用硬编码的方法嵌入三部电话!现在让我们用Angular内建的叫做$http的服务来从我们的服务器获取更大的数据集吧.我们将会使用Angular的依赖注入来为PhoneListCtrl ...

  6. IM 融云 之 列表中显示聊天用户名称

    现在发现,聊天列表中,用户名称没有显示出来.

  7. Redis 排行榜 自己简单练习

    <?php class Ranks{ const PREFIX = 'zhengban'; protected $redis = ''; /* 初始化 */ public function __ ...

  8. 用编程的方式定义UI界面

    package com.example.administrator.test_hello_world; import android.app.Activity; import android.os.B ...

  9. 环信 之 iOS 客户端集成四:集成UI

    在Podfile文件里加入 pod 'EaseUI', :git => 'https://github.com/easemob/easeui-ios-cocoapods.git' 然后在终端中的 ...

  10. 记录一次事故——idea,sbt,scala

    没事千万不要点idea的update啊,就算它自己弹出来的也不要管哦. 我们自己的IDE在使用过程中总会有各种settting的配置,更新之后这些都没有了,而且自己本地安装的插件也就都没有了,所以更新 ...