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. lua weak table 概念解析

    lua weak table 经常看到lua表中有 weak table的用法, 例如: weak_table = setmetatable({}, {__mode="v"}) 官 ...

  2. JQuery选择器转义说明

    JQuery选择器 JQuery选择器规则, 借用了css1-3的规则(css选择器规则), 因为css本身也需要一套规则来索引DOM元素, 进而进行样式渲染,例如div.blue 表示目标DOM为 ...

  3. PRML读书笔记——2 Probability Distributions

    2.1. Binary Variables 1. Bernoulli distribution, p(x = 1|µ) = µ 2.Binomial distribution + 3.beta dis ...

  4. CentOS-6 yum安装nginx php53 mysql55 搭建LNMP环境

    1.导入外部软件库 01.rpm -Uvh http://dl.iuscommunity.org/pub/ius/stable/Redhat/6/x86_64/epel-release-6-5.noa ...

  5. Java多线程编程——进阶篇一

    一.线程栈模型与线程的变量 要理解线程调度的原理,以及线程执行过程,必须理解线程栈模型. 线程栈是指某一时刻内存中线程调度的栈信息,当前调用的方法总是位于栈顶.线程栈的内容是随着程序的运行动态变化的, ...

  6. js 操作 字符串

    去w3school看看string的基本方法把: 方法描述 anchor()    创建 HTML 锚.    big()    用大号字体显示字符串.    blink()    显示闪动字符串.  ...

  7. Web Server 配置及上传文件

    第一种方案:从github上面克隆到服务器 1.git上传文件 ( git bash ) ①切换至所要上传的文件夹 cd 文件夹homepage ②告诉系统当前文件夹要进行git管理 git init ...

  8. Linux phpbb论坛的安装(英文版)

    1:建立文件夹

  9. SnowNLP:一个处理中文文本的 Python 类库

    https://segmentfault.com/a/1190000000362372

  10. libevent源码分析(一)

    分析libevent的源代码,我的想法的是先分析各种结构体,struct event_base.struct event,然后是event_base_new函数.event_new函数.event_a ...