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. ResultSet遍历过程中修改自身数据,不会改变循环的过程

    ResultSet遍历过程中修改自身数据,不会改变循环的过程: import java.sql.Connection; import java.sql.PreparedStatement; impor ...

  2. Java数据库连接--JDBC基础知识(操作数据库:增删改查)

    一.JDBC简介 JDBC是连接java应用程序和数据库之间的桥梁. 什么是JDBC? Java语言访问数据库的一种规范,是一套API. JDBC (Java Database Connectivit ...

  3. 国产数据库-KingbaseES在linux下的安装

    将KingbaseES软件从windows中传至Linux中并解压 [root@localhost ~]# ls anaconda-ks.cfg  install.log.syslog Desktop ...

  4. Java线程:总结

    线程的状态转换图: new:新建状态 Runnable:就绪状态.线程对象创建后,其他线程调用了该对象的start()方法.该状态的线程位于可运行线程池中,变得可运行,等待获取CPU的使用权. Run ...

  5. HTML 颜色名

    目前所有浏览器都支持以下颜色名. 141个颜色名称是在HTML和CSS颜色规范定义的(17标准颜色,再加124).下表列出了所有颜色的值,包括十六进制值.  提示: 17标准颜色:黑色,蓝色,水,紫红 ...

  6. HDU1394(线段树||树状数组)

    Minimum Inversion Number Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java ...

  7. (四)Hololens Unity 开发之 凝视系统

    学习源于官方文档 Gaze in Unity 笔记一部分是直接翻译官方文档,部分各人理解不一致的和一些比较浅显的保留英文原文 HoloLens 有三大输入系统,凝视点.手势和声音 ~ 本文主要记录凝视 ...

  8. phpstrom 的一些常用设置

    phpstrom是php开发者使用率比较高的一款IDE,也是我使用的比较多的一款,以免以后忘记了自己熟悉的设置,在此做一些记录. 1.主题的设置   可以在http://www.phpstorm-th ...

  9. Ubuntu 修改时区

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

  10. C++ Primer 笔记 第二章

    C++ Primer 第二章 变量和基本类型 2.1基本内置类型 有算数类型和void类型:算数类型储存空间大小依及其而定. 算数类型表: 类型 含义 最小储存空间 bool 布尔型 - char 字 ...