什么是面向对象?面向对象是一种思想!(废话)。

  面向对象可以把程序中的关键模块都视为对象,而模块拥有属性及方法。这样我们如果把一些属性及方法封装起来,日后使用将非常方便,也可以避免繁琐重复的工作。接下来将为大家讲解在JS中面向对象的实现。

  工厂模式

  工厂模式是软件工程领域一种广为人知的设计模式,而由于在ECMAScript中无法创建类,因此用函数封装以特定接口创建对象。其实现方法非常简单,也就是在函数内创建一个对象,给对象赋予属性及方法再将对象返回即可。

  1. function createBlog(name, url) {
  2. var o = new Object();
  3. o.name = name;
  4. o.url = url;
  5. o.sayUrl= function() {
  6. alert(this.url);
  7. }
  8. return o;
  9. }
  10.  
  11. var blog1 = createBlog('wuyuchang', 'http://www.cnblogs.com/wuyuchang/');

  可以看到工厂模式的实现方法非常简单,解决了创建多个相似对象的问题,但是工厂模式却无从识别对象的类型,因为全部都是Object,不像Date、Array等,因此出现了构造函数模式。

  

  构造函数模式

  ECMAScript中构造函数可以创建特定类型的对象,类似于Array、Date等原生JS的对象。其实现方法如下:

  1. function Blog(name, url) {
  2. this.name = name;
  3. this.url = url;
  4. this.alertUrl = function() {
  5. alert(this.url);
  6. }
  7. }
  8.  
  9. var blog = new Blog('wuyuchang', 'http://www.cnblogs.com/wuyuchang/');
  10. console.log(blog instanceof Blog); // true, 判断blog是否是Blog的实例,即解决了工厂模式中不能

  这个例子与工厂模式中除了函数名不同以外,细心的童鞋应该发现许多不同之处:

  1. 函数名首写字母为大写  (虽然标准没有严格规定首写字母为大写,但按照惯例,构造函数的首写字母用大写
  2. 没有显示的创建对象
  3. 直接将属性和方法赋值给了this对象
  4. 没有return语句
  5. 使用new创建对象
  6. 能够识别对象(这正是构造函数模式胜于工厂模式的地方)

  构造函数虽然好用,但也并非没有缺点,使用构造函数的最大的问题在于每次创建实例的时候都要重新创建一次方法(理论上每次创建对象的时候对象的属性均不同,而对象的方法是相同的),然而创建两次完全相同的方法是没有必要的,因此,我们可以将函数移到对象外面(也许有些童鞋已经看出缺点,嘘!)。

  1. function Blog(name, url) {
  2. this.name = name;
  3. this.url = url;
  4. this.alertUrl = alertUrl;
  5. }
  6.  
  7. function alertUrl() {
  8. alert(this.url);
  9. }
  10.  
  11. var blog = new Blog('wuyuchang', 'http://www.cnblogs.com/wuyuchang/'),
  12. blog2 = new Blog('cnblogs', 'http://www.cnblogs.com/');
  13. blog.alertUrl(); // http://www.cnblogs.com/wuyuchang/
  14. blog2.alertUrl(); // http://www.cnblogs.com/

  我们将alertUrl设置成全局函数,这样一来blog与blog2访问的都是同一个函数,可是问题又来了,在全局作用域中定义了一个实际只想让Blog使用的函数,显示让全局作用域有些名副其实,更让人无法接受的是在全局作用域中定义了许多仅供特定对象使用的方法,浪费空间不说,显然失去了面向对象封装性了,因此可以通过原型来解决此问题。

  原型模式

  我们创建的每个函数都有prototype(原型)属性,这个属性是一个指针,指向一个对象,而这个对象的用途是包含可以由特定类型的所有实例共享的属性和方法。使用原型对象的好处就是可以让所有对象实例共享它所包含的属性及方法。

  1. function Blog() {
  2. }
  3.  
  4. Blog.prototype.name = 'wuyuchang';
  5. Blog.prototype.url = 'http://www.cnblogs.com/wuyuchang/';
  6. Blog.prototype.friend = ['fr1', 'fr2', 'fr3', 'fr4'];
  7. Blog.prototype.alertInfo = function() {
  8. alert(this.name + this.url + this.friend );
  9. }
  10.  
  11. // 以下为测试代码
  12. var blog = new Blog(),
  13. blog2 = new Blog();
  14. blog.alertInfo(); // wuyuchanghttp://www.cnblogs.com/wuyuchang/fr1,fr2,fr3,fr4
  15. blog2.alertInfo(); // wuyuchanghttp://www.cnblogs.com/wuyuchang/fr1,fr2,fr3,fr4
  16.  
  17. blog.name = 'wyc1';
  18. blog.url = 'http://***.com';
  19. blog.friend.pop();
  20. blog2.name = 'wyc2';
  21. blog2.url = 'http://+++.com';
  22. blog.alertInfo(); // wyc1http://***.comfr1,fr2,fr3
  23. blog2.alertInfo(); // wyc2http://+++.comfr1,fr2,fr3

  原型模式也不是没有缺点,首先,它省略了构造函数传递初始化参数这一环节,结果所有实例在默认情况下都取得了相同的属性值,这样非常不方便,但这还是不是原型的最大问题,原型模式的最大问题在于共享的本性所导致的,由于共享,因此因此一个实例修改了引用,另一个也随之更改了引用。因此我们通常不单独使用原型,而是结合原型模式与构造函数模式。

  混合模式(原型模式  + 构造函数模式)

  1. function Blog(name, url, friend) {
  2. this.name = name;
  3. this.url = url;
  4. this.friend = friend;
  5. }
  6.  
  7. Blog.prototype.alertInfo = function() {
  8. alert(this.name + this.url + this.friend);
  9. }
  10.  
  11. var blog = new Blog('wuyuchang', 'http://www.cnblogs.com/wuyuchang/', ['fr1', 'fr2', 'fr3']),
  12. blog2 = new Blog('wyc', 'http://**.com', ['a', 'b']);
  13.  
  14. blog.friend.pop();
  15. blog.alertInfo(); // wuyuchanghttp://www.cnblogs.com/wuyuchang/fr1,fr2
  16. blog2.alertInfo(); // wychttp://**.coma,b

  混合模式中构造函数模式用于定义实例属性,而原型模式用于定义方法和共享属性。每个实例都会有自己的一份实例属性,但同时又共享着方法,最大限度的节省了内存。另外这种模式还支持传递初始参数。优点甚多。这种模式在ECMAScript中是使用最广泛、认同度最高的一种创建自定义对象的方法。

  动态原型模式

  动态原型模式将所有信息封装在了构造函数中,而通过构造函数中初始化原型(仅第一个对象实例化时初始化原型),这个可以通过判断该方法是否有效而选择是否需要初始化原型。

  1. function Blog(name, url) {
  2. this.name = name;
  3. this.url = url;
  4.  
  5. if (typeof this.alertInfo != 'function') {
  6. // 这段代码只执行了一次
  7. alert('exe time');
  8. Blog.prototype.alertInfo = function() {
  9. alert(thia.name + this.url);
  10. }
  11. }
  12. }
  13.  
  14. var blog = new Blog('wuyuchang', 'http://www.cnblogs.com/wuyuchang'),
  15. blog2 = new Blog('wyc', 'http:***.com');

  可以看到上面的例子中只弹出一次窗,'exe time',即当blog初始化时,这样做blog2就不在需要初始化原型,对于使用这种模式创建对象,可以算是perfect了。

转载自:http://www.cnblogs.com/wuyuchang/p/3908862.html

程序员的基础教程:菜鸟程序员

面向对象JS基础的更多相关文章

  1. 面向对象JS基础讲解,工厂模式、构造函数模式、原型模式、混合模式、动态原型模式

    什么是面向对象?面向对象是一种思想!(废话). 面向对象可以把程序中的关键模块都视为对象,而模块拥有属性及方法.这样我们如果把一些属性及方法封装起来,日后使用将非常方便,也可以避免繁琐重复的工作.接下 ...

  2. JS OOP -01 面向对象的基础

    JS面向对象的基础: 1.用定义函数的方式定义类 2.用new操作符获得一个类的实例 3.使用 [ ] 引用对象的属性和方法 4.动态添加,修改,删除对象的属性和方法 5.使用 { } 语法创建无类型 ...

  3. JS基础入门篇(三十五)—面向对象(二)

    如果没有面向对象这种抽象概念的小伙伴,建议先看一下我写的JS基础入门篇(三十四)-面向对象(一)

  4. js 基础

    js基础知识点总结 如何在一个网站或者一个页面,去书写你的js代码:1.js的分层(功能):jquery(tool) 组件(ui) 应用(app),mvc(backboneJs)2.js的规划():避 ...

  5. JS基础知识总结

      js基础知识点总结 如何在一个网站或者一个页面,去书写你的js代码:1.js的分层(功能):jquery(tool) 组件(ui) 应用(app),mvc(backboneJs)2.js的规划() ...

  6. js基础知识总结(2016.11.1)

    js基础知识点总结 如何在一个网站或者一个页面,去书写你的js代码:1.js的分层(功能):jquery(tool) 组件(ui) 应用(app),mvc(backboneJs)2.js的规划():避 ...

  7. Web3D编程入门总结——WebGL与Three.js基础介绍

    /*在这里对这段时间学习的3D编程知识做个总结,以备再次出发.计划分成“webgl与three.js基础介绍”.“面向对象的基础3D场景框架编写”.“模型导入与简单3D游戏编写”三个部分,其他零散知识 ...

  8. 【 js 基础 】Javascript “继承”

    是时候写一写 "继承"了,为什么加引号,因为当你阅读完这篇文章,你会知道,说是 继承 其实是不准确的. 一.类1.传统的面向类的语言中的类:类/继承 描述了一种代码的组织结构形式. ...

  9. JS基础学习1

    1 JS 概述 一个完整的javascript实现是由以下3个不同部分组成的: (1)     核心(ECMAscript) (2)     文档对象模型(DOM)  Document object ...

随机推荐

  1. JAVA-Unit02: Oracle字符串操作 、 Oracle数值操作 、 Oracle日期操作 、 空值操作

    Unit02: Oracle字符串操作 . Oracle数值操作 . Oracle日期操作 . 空值操作 DQL数据查询语言 查询语句基本由SELECT子句由FROM子句构成. SELECT子句指定要 ...

  2. C++11标准库中cstdio头文件新增的5个格式化I/O函数学习

    刚开始学网络编程,稍微扩展书上的简单C/S程序时,发现以前太忽略标准I/O这一块,查官网发现C++11新增了几个格式化I/O函数. snprintf    将格式化输出写入到有大小限制的缓存中 vfs ...

  3. linux命令之awk

    简介 awk命令的名称是取自三位创始人Alfred Aho .Peter Weinberger 和 Brian Kernighan姓名的首字母,awk有自己的程序设计语言,设计简短的程序,读入文件,数 ...

  4. HDOJ5875(线段树)

    Function Time Limit: 7000/3500 MS (Java/Others)    Memory Limit: 262144/262144 K (Java/Others)Total ...

  5. Html5 input日期时间输入类型标签赋值 正确的格式应该是value="2014-03-15T08:00"

    自己也亲测了!T在php的date函数中格式化后是CST   所以不能写成date('Y-m-dTH:i:s',time()) 得把把年月日和时间用date函数分别格式化  再用大写T分割开  放在v ...

  6. Java 内存机制、内存泄露

    http://wenku.baidu.com/view/61f31da6284ac850ad02423e.html 自己注:hashset和hashmap不同 JDK1.6 API 中 HashSet ...

  7. JavaScript中的跨域详解(一)

    同源策略 所谓的同源策略,指的是浏览器对不同源的脚本或者文本访问方式进行的限制. 所谓同源,就是指两个页面具有相同的协议,主机(也常说域名),端口,三个要素缺一不可. 同源政策的目的,是为了保证用户信 ...

  8. Django模型层

    ORM简介: MVC或者MTV框架中包括一个重要的部分就是ORM,它实现了数据模型与数据库的解耦,即数据模型的设计不需要依赖特定的数据库,通过简单的配置就可以轻松更换数据库,这极大的减轻了开发人员的工 ...

  9. GridControl 添加全选列

    这里通过List对象绑定GridControl,且不用在GirdControl界面中添加任何列,实现CheckBox列的方法 1.列表中出现CheckBox列 非常简单,在绑定的List实体中,增加一 ...

  10. 【转】详解Data Binding 通过几个简单示例深入了解WinForm数据绑定特性

    原文地址:http://www.cnblogs.com/lichence/archive/2012/02/17/2356001.html