Javascript面对对象. 第四篇
原型模式创建对象也有自己的缺点,它省略看构造函数传参初始化这一过程,带来的缺点就是初始化的值都是一致的。
而原型最大的缺点就是它优点,那就是共享。
原型中所有属性是被很多实例共享的,共享对于函数非常合适,对于包含基本值的属性也还可以,但如果属性包含引用类型。
就存在一定的问题:
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面对对象. 第四篇的更多相关文章
- Javascript面对对象. 第五篇
继承 继承是面向对象中一个核心的概念.其他正统面向对象语言都会用两种方式实现继承: 一个是接口实现,一个是继承. 而ECMAScript只支持继承,不支持接口实现,而实现继承的方式依靠原型链完成. / ...
- Javascript面对对象. 第三篇
3.字面量 为了让属性和方法很好的体现封装的效果,并且减少不必要的输入原型的创建可以使用字面量. function Box(){} //使用字面量的方法创建原型对象,这里的{}就是对象,是Object ...
- 深入理解javascript作用域系列第四篇——块作用域
× 目录 [1]let [2]const [3]try 前面的话 尽管函数作用域是最常见的作用域单元,也是现行大多数javascript最普遍的设计方法,但其他类型的作用域单元也是存在的,并且通过使用 ...
- 深入理解javascript作用域系列第四篇
前面的话 尽管函数作用域是最常见的作用域单元,也是现行大多数javascript最普遍的设计方法,但其他类型的作用域单元也是存在的,并且通过使用其他类型的作用域单元甚至可以实现维护起来更加优秀.简洁的 ...
- Javascript面对对象. 第一篇
Javascript,有两个种开发模式: 1.函数式(过程化)2.面对对象(oop),面对对象语言有一个标志,就是类,而通过类可以创建任何多个属性和方法,而Ecmascript没有类的概念,因此它的对 ...
- Javascript面对对象. 第二篇
但是还有一个问题,就是识别的问题,因为根本无法搞清楚他们到底是哪个对象的实例. 1.构造函数 function CreateObject(name,age){ //创建一个对象,使用构造函数的对象都是 ...
- javascript面对对象编程 之继承
上一篇博客中为大家介绍了javascript面向对象编程原则的封装,今天为大家介绍继承.在javascript中没有类的概念,全部不能像c#.java语言那样.直接的用类去继承类.比方如今有比方.如今 ...
- javascript面向对象系列第四篇——选项卡的实现
前面的话 面向对象的应用并非只是读几本书那么容易,需要有大量的工程实践做基础才能真正理解并学会使用它.本文将用面向对象的技术来制作一个简单的选项卡 图示说明 由图示结果看到,这是一个非常简单的选项卡. ...
- 深入理解javascript函数系列第四篇——ES6函数扩展
× 目录 [1]参数默认值 [2]rest参数 [3]扩展运算符[4]箭头函数 前面的话 ES6标准关于函数扩展部分,主要涉及以下四个方面:参数默认值.rest参数.扩展运算符和箭头函数 参数默认值 ...
随机推荐
- HTML 学习笔记 JQuery(表单,表格 操作)
表单应用 一个表单有3个基本组成部分 (1)表单标签:包含处理表单数据所用的服务器端程序URL 以及数据提交到服务器的方法 (2)表单域:包含文本框 密码框 隐藏框 多行文本框 复选框 单选框 下拉选 ...
- Mac OS10.11更新ruby,gem,安装cocoapods
1.装cocoapods,ruby版本忒低->开始更新ruby->开始更新gem,这是一条不归路啊同志们,各种permission denied,各种路径不存在,各种路径没有读写权限,各种 ...
- UVa 10258 - Contest Scoreboard
题目大意:关于acm竞赛排名的题目,对于参赛者首先按做出的题目排名,然后是罚时,最后是编号. 多关键字域排序问题. #include <cstdio> #include <cstri ...
- java中Array/List/Map/Object与Json互相转换详解(转载)
JSON(JavaScript Object Notation) 是一种轻量级的数据交换格式.易于人阅读和编写.同时也易于机器解析和生成.它基于JavaScript Programming Langu ...
- C++第四天学习
回顾: 1.初始化表 2.this指针 3.拷贝构造 Test(const Test& rt) { //1.分配新空间 //2.给新空间赋值 } 4.static成员 类::函数(): 类型 ...
- HDU1217:Arbitrage(SPFA)
题目链接 http://acm.hdu.edu.cn/showproblem.php?pid=1217 题目大意 在每种钱币间进行各种交换,最后换回自己如果能赚,那么就Yes,否则No 注意应为有负权 ...
- --@angularJS--$scope.watch监听模型变化
$watch简单使用 $watch是一个scope函数,用于监听模型变化,当你的模型部分发生变化时它会通知你. $watch(watchExpression, listener, objectEqua ...
- package.json 里 devDependencies和dependencies的区别
我们在使用npm install 安装模块或插件的时候,有两种命令把他们写入到 package.json 文件里面去,比如: --save-dev --save 在 package.json 文件里面 ...
- 建立、配置和使用Activity——Activity
Activity是Android应用中最重要.最常见的应用组件(此处的组件是粗粒度的系统组成部分,并非指界面控件:widget).Android应用的一个重要组成部分就是开发Activity,下 面将 ...
- JavaScript原生的节点操作
前言:原生是Javascript的基础,还是需要多多重视,时间长都忘记了,现在整理一下. 获取子节点 children 不是标准的dom属性,但是几乎被所有浏览器支持.不包含文本节点. 注意:在IE中 ...