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 ...
随机推荐
- CSS图形形状大全
The Shapes of CSS All of the below use only a single HTML element. Any kind of CSS goes, as long as ...
- 【BZOJ 3926】【ZJOI 2015】诸神眷顾的幻想乡
http://www.lydsy.com/JudgeOnline/problem.php?id=3926 广义后缀自动机的例题,感觉广义后缀自动机好恶心... 广义后缀自动机是对一个trie建立的后缀 ...
- PHP安全编程
转自:http://www.nowamagic.net/librarys/veda/detail/2076 1.关闭register_globals,以提高安全性 2.在部署环境,不要让不相关的人 ...
- 基于basys2驱动LCDQC12864B的verilog设计图片显示
话不多说先上图 前言 在做这个实验的时候在网上找了许多资料,都是关于使用单片机驱动LCD显示,确实用单片机驱动是要简单不少,记得在FPGA学习交流群里问问题的时候,被前辈指教,说给我最好的指教便是别在 ...
- 新手Axis2 发布Web Service之路
由于公司的需求,需要写几个银行接口写模拟器(Mock Server),此次接口需要发布成一个WEB Service. 一开始,我以为只要负责写接口的业务层就行了,具体的框架或是环境搭建可以不用管.在与 ...
- Javascript中的async await
async / await是Javascript是ES7的重要特性之一,也是目前社区里公认的优秀异步解决方案.目前,async / await这个特性已经是stage 3的建议,可以看看TC39的进度 ...
- Windows 10 IoT Core环境配置中的那些坑
我使用的设备是Raspberry Pi 3B,想来国内的嵌入式玩具应该还是树莓派最常见吧.这段时间一直在捣鼓Win10 IoT,结果发现,从安装一直到编码调试一路下来全都是坑.写这篇东西一个是为了备忘 ...
- (一)Redis在windows下的安装和使用
1.下载redis服务端,地址:https://github.com/MSOpenTech/redis/releases 包含安装程序和源码. 2.解压<Redis-x64-3.2.100.zi ...
- 使用Navicat Premium 链接本地数据库的方法
在工作中,为了更方便的使用数据库,不免会用到Navicat Premium: 于是在重新安装电脑系统之后,原本想在其中链接一下本地数据库, 只是在链接途中要写的密码一项却不晓得应该写什么,想了很久密码 ...
- java实现解析二进制文件(字符串、图片)
1.需求说明,实现细节要求: 解析二进制文件 files\case10\binary,其中包含一个字符串和一张图片,数据文件格式为字符串数据长度(2字节)+字符串内容+图片数据长度(4字节)+图片数据 ...