1.工厂模式

工厂模式是一种常用的创建对象的模式,可以使用以下函数封装创建对象的细节:

function CreatePerson(name,age){
var p=new Object();
p.name=name;
p.age=age;
p.speak=function(){
console.log("my name is "+p.name);
}
return p;
} var p1=CreatePerson('Wang',15);
p1.speak(); var p2=CreatePerson("Li",18);
p2.speak();

特点:工厂模式实现了创建相似对象的功能,但是缺点是无法确定所创建出来对象的类型。

2.构造函数

①使用构造函数可以创建对象:

function Person(name,age){
this.name=name;
this.age=age;
this.speak=function(){
console.log("my name is "+this.name);
}
}

构造函数和工厂模式区别的地方:没有在函数内显式的创建对象,而是直接将属性赋值给this;没有使用return语句返回。

②调用:使用new操作符调用构造函数创建对象。

//作为构造函数调用
var p1=new Person('Wang',15);
p1.speak();// my name is Wang
var p2=new Person("Li",18);
p2.speak();// my name is Li

调用过程经历了几个步骤:

  • 创建一个新对象;
  • 将构造函数的作用域赋给该对象,此时this也就指向了该对象;
  • 执行构造函数中的代码;
  • 返回该对象。

另外,构造函数也可以作为普通函数调用,此时this指向的是window对象:

Person('chen',15);
window.speak();//my name is chen

③调用构造函数创建的对象,既是Person的实例,也是Object的实例。这一点上比工厂模式略胜一筹。

console.log(p1 instanceof Object);//true
console.log(p1 instanceof Person);//true

④缺点:方法speak要在每个实例上都创建一遍,不能进行共享。

p1.speak==p2.speak;//返回false

3.原型模式

使用原型对象prototype的好处是可以让所有对象实例共享它所包含的属性和方法。

function Person(){
} //原型
Person.protype={
constructor:Person,
name:'Tom',
age:18,
speak:function(){
console.log('my name is '+this.name+',I am '+this.age);
}
} //调用
var p1=new Person();
var p2=new Person();
console.log(p1.speak==p2.speak);//true
console.log(p1.speak());//my name is Tom,I am 18

可以看出Person的实例对象共享了属性和方法。

isPrototypeOf()方法用来检测实例和原型对象之间的关系。

console.log(Person.prototype.isPrototypeOf(p1));//true

当给实例设置与原型中同名的属性时,会给该实例对象新增一个属性,它会屏蔽访问原型中的同名属性值但不会修改原型中的属性值。

p1.name='Cathy';
console.log(p1.name);//Cathy
console.log(p2.name);//Tom

如果想重新访问原型中的属性值,可以使用delete操作符删除实例属性即可。

delete p1.name;
console.log(p1.name);//Tom
console.log(p2.name);//Tom

hasOwnProperty()方法:用来检测某属性是存在于实例中还是存在于原型中。仅当属性存在于实例中时,才返回true。

in 操作符:只要对象存在某属性就返回true,无论是实例属性还是原型属性。

p1.hasOwnProperty('name')//false
"name" in p1;//true
p1.name='Cathy';
p1.hasOwnProperty('name')//true
"name" in p1;//true
p2.hasOwnProperty('name')//false
"name" in p2;//true
delete p1.name;
p1.hasOwnProperty('name')//false
"name" in p1;//true

结合使用hasOwnProperty和in,可以判断属性是不是存在于原型中。

function hasPrototypeProperty(object,name){
return (!object.hasOwnProperty(name))&&(name in object);
}
var p1=new Person();
console.log(hasPrototypeProperty(p1,'name'));//true
p1.name='Peter';
console.log(hasPrototypeProperty(p1,'name'));//false

原型的动态性:对原型所做的修改能够立即从实例中体现出来。

function Person(){
}
var p=new Person();
Person.prototype.speak=function(){
console.log("hello world");
}
p.speak();//hello world

原型模式缺点:实例之间共享所有的原型属性和方法,有些个性化的属性无法体现。

4. * 组合使用构造函数模式和原型模式

这种组合是最常见的一种方式,用构造函数模式创建实例属性,原型模式定义公用的属性和方法。

function Person(name,age)
{
this.name=name;
this.age=age;
this.friends=['lucy','kate']
}
Person.prototype={
constructor:Person,
sayName:function(){
console.log("my name is "+this.name);
}
}
var p1=new Person('Ken',16);
p1.sayName();//my name is Ken
var p2=new Person('Peter',20);
p2.sayName();//my name is Peter
p1.friends.push('Zhang');
console.log(p1.friends);// ["lucy", "kate", "Zhang"]
console.log(p2.friends);// ["lucy", "kate"]

5.动态原型模式

function Person(name,age)
{
this.name=name;
this.age=age;
if(typeof this.sayName!='function'){
Person.prototype.sayName=function(){
console.log("my name is "+this.name);
}
}
}
var p1=new Person('Ken',16);
p1.sayName();//my name is Ken
var p2=new Person('Peter',20);
p2.sayName();//my name is Peter

说明:不必检查原型中的每个属性和方法,只要检查其中一个即可;

不能使用对象字面量方法重写原型。

读javascript高级程序设计05-面向对象之创建对象的更多相关文章

  1. 读javascript高级程序设计00-目录

    javascript高级编程读书笔记系列,也是本砖头书.感觉js是一种很好上手的语言,不过本书细细读来发现了很多之前不了解的细节,受益良多.<br/>本笔记是为了方便日后查阅,仅作学习交流 ...

  2. 读javascript高级程序设计-目录

    javascript高级编程读书笔记系列,也是本砖头书.感觉js是一种很好上手的语言,不过本书细细读来发现了很多之前不了解的细节,受益良多.<br/>本笔记是为了方便日后查阅,仅作学习交流 ...

  3. 读javascript高级程序设计08-引用类型之Global、Math、String

    一.Global 所有在全局作用域定义的属性和方法,都属于Global对象. 1.URI编码: encodeURI():主要用于对整个URI编码.它不会对本身属于URI的特殊字符进行编码. encod ...

  4. 读Javascript高级程序设计第三版第六章面向对象设计--创建对象

    虽然Object构造函数或者对象字面量都可以用来创建单个对象,但是缺点非常明显:使用同一接口创建很多对象,会产生大量重复代码. 工厂模式  1 function CreatePerson(name,a ...

  5. 读javascript高级程序设计07-引用类型、Object、Array

    一.引用类型 ECMAScript是支持面向对象的,可以通过引用类型描述一类对象所具有的属性和方法. 创建对象实例的方法时是用new 操作符加构造函数:var p=new Person(). 二.Ob ...

  6. 读javascript高级程序设计10-DOM

    一.节点关系 元素的childNodes属性来表示其所有子节点,它是一个NodeList对象,会随着DOM结构的变化动态变化. hasChildNodes():是否有子节点. var headline ...

  7. 读javascript高级程序设计15-Ajax,CORS,JSONP,Img Ping

    平时用惯了jQuery.ajax之类的方法,却时常忽略了它背后的实现,本文是学习了AJAX基础及几种跨域解决方案之后的一些收获. 一.AJAX——XMLHttpRequest 谈起Ajax我们都很熟悉 ...

  8. 《JavaScript高级程序设计》读书笔记 ---创建对象

    虽然Object 构造函数或对象字面量都可以用来创建单个对象,但这些方式有个明显的缺点:使用同一个接口创建很多对象,会产生大量的重复代码.为解决这个问题,人们开始使用工厂模式的一种变体. 工厂模式工厂 ...

  9. 读javascript高级程序设计17-在线检测,cookie,子cookie

    一.在线状态检测 开发离线应用时,往往在离线状态时把数据存在本地,而在联机状态时再把数据发送到服务器.html5提供了检测在线状态的方法:navigator.onLine和online/offline ...

随机推荐

  1. dubbo源码分析5-dubbo的扩展点机制

    dubbo源码分析1-reference bean创建 dubbo源码分析2-reference bean发起服务方法调用 dubbo源码分析3-service bean的创建与发布 dubbo源码分 ...

  2. NULLIF()函数使用讲解

    NULLIF()函数接受两个参数.如果它们相等,那么返回空值:否则,返回第一个参数. 等价于下面的表达式: case when expression1=expression2 then null el ...

  3. oracle数据导出工具sqluldr2

    oracle数据导出工具sqluldr2可以将数据以csv.txt等格式导出,适用于大批量数据的导出,导出速度非常快.导出后可以使用oracle loader工具将数据导入.下载完sqluldr2,工 ...

  4. Velocity(9)——宏

    定义宏和使用宏 #macro指令用于定义一个VTL模板的重复代码块——宏.下面是一个简单的定义宏的例子: #macro( d ) <tr><td></td>< ...

  5. csuoj 1505: 酷酷的单词

    http://acm.csu.edu.cn/OnlineJudge/problem.php?id=1505 1505: 酷酷的单词 时间限制: 1 Sec  内存限制: 128 MB 提交: 340  ...

  6. html drag 拖拽用法和注意事项

    1.拖拽过程中的事件暂时jQuery里还没有,只能通过html DOM 来进行绑定,不然无法获取dataTransfer对象 2.在dragstart .dragover 等事件中可以用 evt.pr ...

  7. 关于xfce中桌面没法显示回收站以及thunar中无法进行卷管理的解决办法

    出现这种问题的原因应该不是当前用户没在storage这个组里,因为我试过将用户从storage组里移除并不对影响桌面上回收站的显示. 问题的原因是没有安装gvfs这个软件,装上之后,重新登录当前用户, ...

  8. Spring aop报错:com.sun.proxy.$Proxy cannot be cast to xxx

    准备使用AOP记录所有NamedParameterJdbcTemplate操作数据时的所有日志,没想到出现这个错误,折腾了好久,终于找出原因 解决方案:在 aop-config配置添加上: proxy ...

  9. 自定义分词器Analyzer

    Analyzer,或者说文本分析的过程,实质上是将输入文本转化为文本特征向量的过程.这里所说的文本特征,可以是词或者是短语.它主要包括以下四个步骤: 1.分词,将文本解析为单词或短语 2.归一化,将文 ...

  10. [已解决] MyBatis 中bind用法

    JAVA: TC_ENTR_FLOW selectFlowForUpdate(String ENTR_ID); XML: <select id="selectFlowForUpdate ...