作者: 阮一峰

原文地址:http://www.ruanyifeng.com/blog/2012/07/three_ways_to_define_a_javascript_class.html

将近20年前,Javascript诞生的时候,只是一种简单的网页脚本语言。如果你忘了填写用户名,它就跳出一个警告。

如今,它变得几乎无所不能,从前端到后端,有着各种匪夷所思的用途。程序员用它完成越来越庞大的项目。

Javascript代码的复杂度也直线上升。单个网页包含10000行Javascript代码,早就司空见惯。2010年,一个工程师透露,Gmail的代码长度是443000行!

编写和维护如此复杂的代码,必须使用模块化策略。目前,业界的主流做法是采用"面向对象编程"。因此,Javascript如何实现面向对象编程,就成了一个热门课题。

麻烦的是,Javascipt语法不支持"类"(class),导致传统的面向对象编程方法无法直接使用。程序员们做了很多探索,研究如何用Javascript模拟"类"。本文总结了Javascript定义"类"的三种方法,讨论了每种方法的特点,着重介绍了我眼中的最佳方法。

在面向对象编程中,类(class)是对象(object)的模板,定义了同一组对象(又称"实例")共有的属性和方法。

Javascript语言不支持"类",但是可以用一些变通的方法,模拟出"类"。

一、构造函数

它用构造函数模拟"类",在其内部用this关键字指代实例对象。

function Cat() {
    this.name = "cat";
  }

生成实例的时候,使用new关键字。

var cat1 = new Cat();
  alert(cat1.name); // cat

类的属性和方法,还可以定义在构造函数的prototype对象之上。

 Cat.prototype.makeSound = function(){
    alert("this is a cat");
  }

关于这种方法的详细介绍,请看我写的系列文章《Javascript 面向对象编程》,这里就不多说了。它的主要缺点是,比较复杂,用到了this和prototype,编写和阅读都很费力。

二、Object.create()

为了解决"构造函数法"的缺点,更方便地生成对象,Javascript的国际标准ECMAScript第五版(目前通行的是第三版),提出了一个新的方法Object.create()

用这个方法,"类"就是一个对象,不是函数。

 var Cat = {
    name: "cat",
    makeSound: function(){ alert("this is a cat"); }
  };

然后,直接用Object.create()生成实例,不需要用到new。

var cat1 = Object.create(Cat);
  alert(cat1.name); // cat
  cat1.makeSound();//this is a cat

目前,各大浏览器的最新版本(包括IE9)都部署了这个方法。如果遇到老式浏览器,可以用下面的代码自行部署。

  if (!Object.create) {
    Object.create = function (o) {
       function F() {}
      F.prototype = o;
      return new F();
    };
  }

这种方法比"构造函数法"简单,但是不能实现私有属性和私有方法,实例对象之间也不能共享数据,对"类"的模拟不够全面。

三、极简主义

荷兰程序员Gabor de Mooij提出了一种比Object.create()更好的新方法,他称这种方法为"极简主义法"(minimalist approach)。这也是我推荐的方法。

3.1封装

这种方法不使用this和prototype,代码部署起来非常简单,这大概也是它被叫做"极简主义法"的原因。

首先,它也是用一个对象模拟"类"。在这个类里面,定义一个构造函数createNew(),用来生成实例。

 var Cat = {
    createNew: function(){
      // some code here
    }
  };

然后,在createNew()里面,定义一个实例对象,把这个实例对象作为返回值。

 var Cat = {
    createNew: function(){
      var cat = {};
      cat.name = "cat";
      cat.makeSound = function(){ alert("this is a cat"); };
      return cat;
    }
  };

使用的时候,调用createNew()方法,就可以得到实例对象。

var cat1 = Cat.createNew();
  cat1.makeSound();//this is a cat

这种方法的好处是,容易理解,结构清晰优雅,符合传统的"面向对象编程"的构造,因此可以方便地部署下面的特性。

3.2继承

让一个类继承另一个类,实现起来很方便。只要在前者的createNew()方法中,调用后者的createNew()方法即可。

先定义一个Animal类。

var Animal = {
    createNew: function(){
      var animal = {};
      animal.sleep = function(){ alert("sleep"); };
      return animal;
    }
  };

然后,在Cat的createNew()方法中,调用Animal的createNew()方法。

var Cat = {
    createNew: function(){
      var cat = Animal.createNew();
      cat.name = "大毛";
      cat.makeSound = function(){ alert("this is a cat"); };
      return cat;
    }

这样得到的Cat实例,就会同时继承Cat类和Animal类。

 var cat1 = Cat.createNew();
  cat1.sleep(); // sleep

3.3私有属性和私有方法

 var Cat = {
    createNew: function(){
      var cat = {};
      var sound = "this is a cat";
      cat.makeSound = function(){ alert(sound); };
      return cat;
    }
  };

上例的内部变量sound,外部无法读取,只有通过cat的公有方法makeSound()来读取。

 var cat1 = Cat.createNew();
  alert(cat1.sound); // undefined

3.4数据共享

有时候,我们需要所有实例对象,能够读写同一项内部数据。这个时候,只要把这个内部数据,封装在类对象的里面、createNew()方法的外面即可。

 var Cat = {
    sound : "sound",
    createNew: function(){
      var cat = {};
      cat.makeSound = function(){ alert(Cat.sound); };
      cat.changeSound = function(x){ Cat.sound = x; };
      return cat;
    }
  };

然后,生成两个实例对象:

var cat1 = Cat.createNew();
  var cat2 = Cat.createNew();
  cat1.makeSound(); // sound

这时,如果有一个实例对象,修改了共享的数据,另一个实例对象也会受到影响。

 cat2.changeSound("hello");
  cat1.makeSound(); // hello

[转]Javascript定义类的三种方法的更多相关文章

  1. JavaScript定义类的几种方式

    提起面向对象我们就能想到类,对象,封装,继承,多态.在<javaScript高级程序设计>(人民邮电出版社,曹力.张欣译.英文名字是:Professional JavaScript for ...

  2. javascript生成对象的三种方法

    /** js生成对象的三种方法*/ // 1.通过new Object,然后添加属性 示例如下: var people1 = new Object(); people1.name = 'xiaohai ...

  3. [转]SharePoint 2010/2013 使用Javascript来判断权限的三种方法

    本文讲述SharePoint 2010/2013 使用Javascript来判断权限的三种方法的实现方式及其优缺点. 1. 根据用户所在的SharePoint组(比如用户在Leader 组才可以使用审 ...

  4. javascript函数 (二 定义函数的三种方法)

    javascript定义函数(声明函数)可以有三种方法:正常方法.构造函数.函数直接量 <html><head></head><body> <sc ...

  5. C++中定义比较函数的三种方法

    原文地址:http://fusharblog.com/3-ways-to-define-comparison-functions-in-cpp/ C++编程优与Pascal的原因之一是C++中存在ST ...

  6. Javascript创建类的七种方法

    /* 第一种定义类的方法 */var cls = new Object();cls.name = "wyf";cls.showName = function(){console.l ...

  7. JavaScript去除空格的三种方法(正则/传参函数/trim)

    方法一: 个人认为最好的方法.采用的是正则表达式,这是最核心的原理. 其次.这个方法使用了JavaScript 的prototype 属性 其实你不使用这个属性一样可以用函数实现.但这样做后用起来比较 ...

  8. JavaScript 复制变量的三种方法

    参考:Copying Objects in JavaScript - Orinami Olatunji(@orinamio_) October 23, 2017    直接将一个变量赋给另一个变量时, ...

  9. JavaScript RegExp 对象的三种方法

    JavaScript RegExp 对象有 3 个方法:test().exec() 和 compile().(1) test() 方法用来检测一个字符串是否匹配某个正则表达式,如果匹配成功,返回 tr ...

随机推荐

  1. 在windows系统上安装VMware Workstation虚拟机,然后在虚拟机VMware Workstation上安装linux系统,在linux系统安装xshell的服务端,在windows系统上安装xshell。用windows系统上的xshell连接到linux

    第一步:安装xshell: 去百度   xshell ,然后安装一下就可以了.就是普通的软件安装,在这里不做过多的接收. 第二步:安装虚拟机VMware Workstation 百度安装,不做过介绍 ...

  2. solr在电商平台中的使用示例简析

    来源:http://blog.csdn.net/yangbutao/article/details/9450463 在电商平台中搜索是非常重要的功能,主要包括有搜索词类目导航.自动提示和搜索排序功能 ...

  3. 利用SOLR搭建企业搜索平台 之——solr的查询语法

      1. 首先假设我的数据里fields有:name, tel, address 预设的搜寻是name这个字段, 如果要搜寻的数据刚好就是 name 这个字段,就不需要指定搜寻字段名称. 2. 查询规 ...

  4. c语言类型转换注意事项

    转载自: http://blog.csdn.net/zhuimengzh/article/details/6728492 1.隐式转换     C在以下四种情况下会进行隐式转换:        1.算 ...

  5. 自定义View(9)关于onLayout

    1,何时被调用 当外层容器组件调用其内部组件的layout(l,r,t,b)时,内部组件的onLayout就被调用.与onMeasure类似. 2,注意 onLayout对ViewGroup及子类才有 ...

  6. Server-Side UI Automation Provider - WinForm Sample

    Server-Side UI Automation Provider - WinForm Sample 2014-09-14 源代码  目录 引用程序集提供程序接口公开服务器端 UI 自动化提供程序从 ...

  7. innodb锁之间的兼容性判断

    检查锁与锁之间的兼容性 路径:/mysql-5.5.43/storage/innobase/lock/lock0lock.c 实现:见锁的强度比较  row 可理解为 lock 的锁模式  colum ...

  8. 如何在linux中从源代码编译安装nodejs?

    $ sudo yum groupinstall 'Development Tools'安装开发环境$ wget https://nodejs.org/dist/v0.12.2/node-v0.12.2 ...

  9. Qt之模型/视图(自定义进度条)

    简述 在之前的章节中分享过关于QHeaderView表头排序.添加复选框等内容,相信大家模型/视图.自定义风格有了一定的了解,下面我们来分享一个更常用的内容-自定义进度条. 实现方式: 从QAbstr ...

  10. hdu 4647 Another Graph Game

    题意: 有N个点,M条边. 点有权值, 边有权值. Alice, Bob 分别选点. 如果一条边的两个顶点被同一个人选了, 那么能获得该权值.问 Alice - Bob? 链接:http://acm. ...