JavaScript设计模式之构造器、模块和原型
JavaScript面向对象
JavaScript是一种无类语言,但可以使用函数来模拟,这就涉及到设计模式。模式是一种已经验证过的可复用的解决方案,可用于解决软件设计中遇到的常见的问题,通常将这些解决方案制作成模板来复用。
而JavaScript模拟类常用的方式是定义一个JavaScript函数,使用this来定义属性和方法,然后使用new关键字创建对象实例。如
function webSite(){
this.name="开源视窗";
this.url="oseye.net";
this.getInfo=function(){
return this.name+" : "+this.url;
}
}
var wb=new webSite();
console.log(wb.getInfo());
创建对象
在JavaScript中,创建新对象的两种常用方法如:
var newObject={};
var newObject=new Object();
然而这两种方式只是创建一个空对象,没有任何用处,但有一下四种方式可以扩展它:
var webSite={};
//"点"语法
webSite.url="oseye.net";
webSite.getInfo=function(){
return this.url;
}
console.log(webSite.getInfo());
console.log(webSite.url);
//中括号语法
webSite["name"]="开源视窗";
console.log(webSite.name);
console.log(webSite["name"]);
//用Object.defineProperty
Object.defineProperty(webSite,"url",{
value:"oseye.net by defineProperty",
writable:true,
enumerable:true,
configurable:true
});
console.log(webSite.url);
//使用Object.defineProperties
Object.defineProperties(webSite,{
"url":{
value:"oseye.net by defineProperties",
writable:true,
enumerable:true,
configurable:true
},
"name":{
value:"开源视窗 by defineProperties",
writable:true
}
});
console.log(webSite.url + webSite.name);
而使用Object.create可以实现继承,如:
var webSite={};
webSite.url="oseye.net";
//创建myWebSite继承自webSite
var myWebSite=Object.create(webSite);
console.log(myWebSite.url);
Constructor(构造器)模式
在经典面向对象编程语言中,构造器是一种在内存已经分配给对象的情况下,用于初始化新创建对象的特殊方法。虽然JavaScript不支持类的概念,但它确实支持与对象一起用的特殊构造器函数,如:
function webSite(name,url){
this.url=url;
this.name=name;
this.getInfo=function(){
return this.url+" - "+this.name;
}
}
var ws=new webSite("开源视窗","oseye.net");
console.log(ws.getInfo());
Module(模块)模式
模块模式是基于对象字面量的,因此需要认识对象字面量的含义。在对象字面量表示法中,一个对象被描述为一组包含大括号({})中、以逗号分隔的name/value对,而谨记对象的最后一个name/value后面不需要逗号,否则语法错误。语法如下:
var newObject={
variableKey:variableValue,
fucntionKey:function(){
//.....
}
};
示例:
var webSite={
url:"oseye.net",
getInfo:function(){
return this.url;
}
};
console.log(webSite.getInfo());
Prototype(原型)模式
每个JavaScript对象都有一个prototype属性,使用使用prototype属性,可以给类动态地添加方法,以便在JavaScript中实现“继承”的效果。其实prototype属性是指向一个对象的引用,这个对象称为原型对象,原型对象包含函数实例共享的方法和属性,也就是说将函数用作构造函数调用(使用new操作符调用)的时候,新创建的对象会从原型对象上继承属性和方法。
看到上面的描述,新手一定云里雾里的!在理解prototype之前我们来看几个面向对象中常见的东东:
- 私有变量、函数:在函数内定义的变量和函数如果不对外提供接口,那么外部将无法访问到,也就是变为私有变量和私有函数
function webSite(){
url="oseye.net";
var getInfo=function(){
}
};
//在webSite对象外部无法访问变量url和函数getInfo,它们就变成私有的,只能在webSite内部使用.
//即使是函数webSite的实例仍然无法访问这些变量和函数,异常提示“undefined”
console.log(new webSite().getInfo()); - 静态变量、函数:当定义一个函数后通过 “.”为其添加的属性和函数,通过对象本身仍然可以访问得到,但是其实例却访问不到,这样的变量和函数分别被称为静态变量和静态函数,用过Java、C#的同学很好理解静态的含义。
function webSite(){};
webSite.url="oseye.net"; console.log(webSite().url); //oseye.net
console.log(new webSite().url); //undefined - 实例变量、函数:在面向对象编程中除了一些库函数我们还是希望在对象定义的时候同时定义一些属性和方法,实例化后可以访问,JavaScript是通过this做到的
function webSite(){
this.url="oseye.net";
this.getInfo=function(){
return this.url;
}
}; console.log(new webSite().url); //oseye.net
console.log(new webSite().getInfo()); //oseye.net看着还不错,但你再看
function webSite(){
this.url="oseye.net";
this.getInfo=function(){
return this.url;
}
}; var ws=new webSite();
ws.url="test.oseye.net";
ws.getInfo=function(){
return "override getInfo";
} console.log(ws.url); //test.oseye.net
console.log(ws.getInfo()); //override getInfo var ws2=new webSite();
console.log(ws2.url); //oseye.net
console.log(ws2.getInfo()); //oseye.net由此可以得出一个结论:每个实例的属性和方法都是对象属性和方法的一个复制。如果一个对象有成千上万个实力方法,那么每个实例都要这么一个复制,有点小恐怖!!这时prototype应运而生,
无论什么时候,只要创建了一个新函数,就会根据一组特定的规则为该函数创建一个prototype属性,默认情况下prototype属性会默认获得一个constructor(构造函数)属性,这个属性是一个指向prototype属性所在函数的指针,有些绕了啊,写代码、上图!
function Person(){}

根据上图可以看出Person对象会自动获得prototyp属性,而prototype也是一个对象,会自动获得一个constructor属性,该属性正是指向Person对象。
当调用构造函数创建一个实例的时候,实例内部将包含一个内部指针(很多浏览器这个指针名字为__proto__)指向构造函数的prototype,这个连接存在于实例和构造函数的prototype之间,而不是实例与构造函数之间。
function Person(name){
this.name=name;
}
Person.prototype.printName=function(){
alert(this.name);
}
var person1=new Person('Byron');
var person2=new Person('Frank');

Person的实例person1中包含了name属性,同时自动生成一个__proto__属性,该属性指向Person的prototype,可以访问到prototype内定义的printName方法,大概就是这个样子的

写段程序测试一下看看prototype内属性、方法是能够共享
function Person(name){
this.name=name;
}
Person.prototype.share=[];
Person.prototype.printName=function(){
alert(this.name);
}
var person1=new Person('Byron');
var person2=new Person('Frank');
person1.share.push(1);
person2.share.push(2);
console.log(person2.share); //[1,2]
果不其然!实际上当代码读取某个对象的某个属性的时候,都会执行一遍搜索,目标是具有给定名字的属性,搜索首先从对象实例开始,如果在实例中找到该属性则返回,如果没有则查找prototype,如果还是没有找到则继续递归prototype的prototype对象,直到找到为止,如果递归到object仍然没有则返回错误。同样道理如果在实例中定义如prototype同名的属性或函数,则会覆盖prototype的属性或函数。
当然prototype不是专门为解决上面问题而定义的,但是却解决了上面问题。了解了这些知识就可以构建一个科学些的、复用率高的对象,如果希望实例对象的属性或函数则定义到prototype中,如果希望每个实例单独拥有的属性或方法则定义到this中,可以通过构造函数传递实例化参数。
JavaScript设计模式之构造器、模块和原型的更多相关文章
- JavaScript设计模式-单例模式、模块模式(转载 学习中。。。。)
(转载地址:http://technicolor.iteye.com/blog/1409656) 之前在<JavaScript小特性-面向对象>里面介绍过JavaScript面向对象的特性 ...
- javascript设计模式:构造器模式学习一
javascript 设计模式1.简介javascript是一种弱类型语言,不过类可以通过函数模拟出来最常见的实现方法如下:function Car(model){ this.model = mode ...
- JavaScript设计模式 -- 读书笔记
JavaScript设计模式 一. 设计模式 一个模式就是一个可重用的方案: 有效的解决方法.易重用.善于表达该解决方案: 未通过"模式特性"测试的模式称为模式原型: 三规则:适用 ...
- 常用的JavaScript设计模式(一)Constructor(构造器)模式
在es6中,新增了一个语法糖--class,可以说是为JavaScript引入了类的概念.而在传统的JavaScript中,则是通过构造器生成实例对象的. JavaScript支持特殊的constru ...
- 再起航,我的学习笔记之JavaScript设计模式09(原型模式)
我的学习笔记是根据我的学习情况来定期更新的,预计2-3天更新一章,主要是给大家分享一下,我所学到的知识,如果有什么错误请在评论中指点出来,我一定虚心接受,那么废话不多说开始我们今天的学习分享吧! 我们 ...
- JavaScript设计模式 (1) 原型模式
原型模式(Prototype):用原型实例指向创建类对象,使用于创建新对象的类共享原型对象的属性以及方法. //图片轮播类 var LoopImages = function (imgArr, con ...
- JavaScript设计模式:读书笔记(未完)
该篇随我读书的进度持续更新阅读书目:<JavaScript设计模式> 2016/3/30 2016/3/31 2016/4/8 2016/3/30: 模式是一种可复用的解决方案,可用于解决 ...
- JavaScript的学习--JavaScript设计模式的总结
这篇博客只是自己对设计模式的理解的备忘~ 看完了<JavaScript设计模式>这本书,一直没有写博客记录一下,最近抽出时间来重读了一下,就顺便记录一下~ 如果你只是想粗略了解一下Java ...
- Javascript设计模式详解
Javascript常用的设计模式详解 阅读目录 一:理解工厂模式 二:理解单体模式 三:理解模块模式 四:理解代理模式 五:理解职责链模式 六:命令模式的理解: 七:模板方法模式 八:理解javas ...
随机推荐
- php字符串比较
比较两个字符串是否相等,最常见的方法就是使用“===”来判断,至于它和“==”的区别,简单来说 就是前者强调“identical”类型也要求一样:后者要求“equal”,值相同就可以了.或者使用str ...
- 多因子降维法(MDR,multifactor dimensionality reduction)
多因子降维法(MDR,Multifactor Dimensionality Reduction ) MDR是近年统计学中发展起来的一种新的分析方法.其中,“因子” 即交互作用研究中的变量,“维” 是指 ...
- PHP中PDO错误/异常(PDOException)处理
PDO 提供了三种不同的错误处理模式,以满足不同风格的应用开发: PDO::ERRMODE_SILENT 此为默认模式. PDO 将只简单地设置错误码,可使用 PDO::errorCode() 和 P ...
- Delphi获取其它进程窗口句柄的3种方法
本文主要跟大家介绍Delphi中获取其它进程的窗口句柄,在Delphi中获取其它进程的窗口句柄,绝大部分人首先想到的会使用:FindWindow或者用GetWindow来遍历查找,如: handle ...
- package.json 里 devDependencies和dependencies的区别
我们在使用npm install 安装模块或插件的时候,有两种命令把他们写入到 package.json 文件里面去,比如: --save-dev --save 在 package.json 文件里面 ...
- document.body.clientHeight的取值
http://www.cnblogs.com/fullhouse/archive/2012/01/05/2313800.html 有时候需要取页面的底部, 就会用到document.body.clie ...
- POI-处理大Excel文件(xls)
最近需要处理一个比较大的excel文件,但是poi在处理文件时会抛出OOM导致程序崩溃,查看官方文档看到可以以流式的方式读取excel避免读取大文件时的OOM.本文主要记述xls的处理. 环境模拟 先 ...
- ubuntu 下配置Web服务器
ubuntu 下配置Web服务器 1.切换管理员身份 终端/文本界面输入命令: su 根据提示输入密码 注: 如果不能使用su 点击查看如何启用su2.安装MySQL5 apt-get install ...
- C# OpenFileDialog 使用
OpenFileDialog ofd = new OpenFileDialog(); //设置标题 ofd.Title = "选择文件"; //是否保存上次打开文件的位置 ofd. ...
- 用Hashcat每秒计算1.4亿个密码,破解隔壁WIFI密码
Hashcat是啥 Hashcat是什么呢?Hashcat是当前最强大的开源密码恢复工具,你可以访问Hashcat.net网站来了解这款工具的详细情况.本质上,Hashcat 3.0是一款高级密码恢复 ...