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设计模式之构造器、模块和原型的更多相关文章

  1. JavaScript设计模式-单例模式、模块模式(转载 学习中。。。。)

    (转载地址:http://technicolor.iteye.com/blog/1409656) 之前在<JavaScript小特性-面向对象>里面介绍过JavaScript面向对象的特性 ...

  2. javascript设计模式:构造器模式学习一

    javascript 设计模式1.简介javascript是一种弱类型语言,不过类可以通过函数模拟出来最常见的实现方法如下:function Car(model){ this.model = mode ...

  3. JavaScript设计模式 -- 读书笔记

    JavaScript设计模式 一. 设计模式 一个模式就是一个可重用的方案: 有效的解决方法.易重用.善于表达该解决方案: 未通过"模式特性"测试的模式称为模式原型: 三规则:适用 ...

  4. 常用的JavaScript设计模式(一)Constructor(构造器)模式

    在es6中,新增了一个语法糖--class,可以说是为JavaScript引入了类的概念.而在传统的JavaScript中,则是通过构造器生成实例对象的. JavaScript支持特殊的constru ...

  5. 再起航,我的学习笔记之JavaScript设计模式09(原型模式)

    我的学习笔记是根据我的学习情况来定期更新的,预计2-3天更新一章,主要是给大家分享一下,我所学到的知识,如果有什么错误请在评论中指点出来,我一定虚心接受,那么废话不多说开始我们今天的学习分享吧! 我们 ...

  6. JavaScript设计模式 (1) 原型模式

    原型模式(Prototype):用原型实例指向创建类对象,使用于创建新对象的类共享原型对象的属性以及方法. //图片轮播类 var LoopImages = function (imgArr, con ...

  7. JavaScript设计模式:读书笔记(未完)

    该篇随我读书的进度持续更新阅读书目:<JavaScript设计模式> 2016/3/30 2016/3/31 2016/4/8 2016/3/30: 模式是一种可复用的解决方案,可用于解决 ...

  8. JavaScript的学习--JavaScript设计模式的总结

    这篇博客只是自己对设计模式的理解的备忘~ 看完了<JavaScript设计模式>这本书,一直没有写博客记录一下,最近抽出时间来重读了一下,就顺便记录一下~ 如果你只是想粗略了解一下Java ...

  9. Javascript设计模式详解

    Javascript常用的设计模式详解 阅读目录 一:理解工厂模式 二:理解单体模式 三:理解模块模式 四:理解代理模式 五:理解职责链模式 六:命令模式的理解: 七:模板方法模式 八:理解javas ...

随机推荐

  1. LNAMP 中的PHP探针

    <?php /* ----------------本探针基于YaHei.net探针------------------- */ error_reporting(0); //抑制所有错误信息 @h ...

  2. C# 常用工具合集

    Visual Studio 2013 扩展 Visual Studio 2013 Update 4:是目前微软发布的最新版开发工具升级包,高效而且强大.下面的扩展都是该版本的Visual Studio ...

  3. 如何在asp.net页面使用css和js

    一.如何在asp.net页面中使用css1.可以直接写在需要样式控制的控件里 例如:<div style="border:#ff6100 1px solid">< ...

  4. 负载均衡软件LVS分析一(概念)

    一. LVS简介LVS是Linux Virtual Server的简称,也就是Linux虚拟服务器, 是一个由章文嵩博士发起的自由软件项目,它的官方站点是www.linuxvirtualserver. ...

  5. CodeForces 460B

    Little Dima and Equation Time Limit:1000MS     Memory Limit:262144KB     64bit IO Format:%I64d & ...

  6. Ubuntu 修改时区

    1. 使用命令行 sudo tzselect 根据提示完成修改 2.修改~/.profile文件 添加: TZ='Asia/Shanghai'; export TZ 注销后重新登陆生效

  7. Android客户端连接服务器端,向服务器端发送请求HttpURLConnection

    在Java中想后台服务器发送请求一般都直接使用了Java的网络编程,或者使用HttpClient向后台服务器端发送HTTP请求.虽然在安卓中,所有Java的API都可以使用,而却使用其并不会出现什么问 ...

  8. StringUtils工具类常用方法介绍(持续更新)

    StringUtils方法的操作对象是java.lang.String类型的对象,是JDK提供的String类型操作方法的补充,并且是null安全的(即如果输入参数String为null则不会抛出Nu ...

  9. (@WhiteTaken)设计模式学习——简单工厂

    最近工作比较忙,所以没有怎么写博客,这几天将集中学习一下(厉风行)讲解的设计模式的相关知识,并对主要的代码进行介绍. 言归正传,接下来介绍最简单也是最基础的简单工厂设计模式. 什么是简单工厂? 简单工 ...

  10. Centos 7安装oracle 11g R2问题及解决方法汇总

    自己新博客的链接:http://www.pythonsite.com/2017/02/14/centos-7%E5%AE%89%E8%A3%85oracle-11g-r2%E9%97%AE%E9%A2 ...