Javascript构造函数和prototype实现封装继承

原创 2013年12月13日 23:08:47

像Java、c++那样的强类型语言,类型是一切对象的模板,通过类型定义,可以描述(封装)数据和操作。根据需求,类型可以扩展继承、多态变化,使得代码的重用性和可读性相比过程化编程语法大大提高。 Javascript也是一门面向对象的语言,在没有类型定义的情况,通过定义原型来实现类型模板。

Javascript引用类型:Javascript本身提供了几种不同的用类型: Function, Object, Boolean, Number, String, Array

其中Function 这个类型最为特殊,必须拿出来单独的说一下,首先必须知道Javascript的所谓的类型不是用class来表示,而是用function来表示,这个类型信息本身就是一个对象。如果按照Java中类型及对象的定义来理解十分不容易,

例如Javascript 定义一个类型为Function的对象如下:

function Cat(){
      return 1;
};

这段代码中Cat扮演两个角色,一个是自定义类型Cat,一个是对象Cat;Cat的类型是Function, 同时Cat又是引用类型Function的一个实例。

作为自定义类型,Cat就可以作为对象的模板,也就是构造函数,实际上Javascript也只能通过定义Function类型创建其他对象的模板,相当于Java中的Class, Object 这个(Function)类型,就相当于Java中的Object类 。例如: new Object(); new Function(); new Array();  所以,Function, Number, Array 这些类型都可以看做是Object(Function)的子类, 除了这些内置引用类型,还可以通过关键字function/Function定义类型, 上面的代码是一种定义Function Cat类型和实例的方式,也同样通过调用特殊的模板函数Function来创建一个类型为Function的实例:

var Cat = new Function("return 1;");

在使用上,Cat不同的身份也分别有不同的用法,作为类型模板,它可以充当构造函数来创建实例,例如: var cat = new Cat(); 当然实例实际上没有任何自己的属性,全部继承了Object 实例;

创建Object实例的方法: var o = new Object();  var o  = {}; 

创建Function实例的方法: var f = new Function("return 1");  var f =function(){return 1;}

Object.constructor ==  Function, Object的构造函数是实际上还是Function方法 

就是说所有的实例都是通过构造函数Function创建出来的


先来简单粗暴的创建一个实例:

  var cat = {name:  'xiaoqi', age: 1};

通过cat.constructor属性或者cat instanceof Object,cat是Object函数构造出来的一个实例,cat的所有属性都继承子Obeject函数, 除了name和age。

上面的代码也可以替换成:

var cat  =new Object();
cat.name = 'xiaoqi';
cat.age ='1';


Object 函数是一切对象的原始模板

如果熟悉Java和C++的开发人员,要理解Object函数是一切对象的模板,就要改变既有的观念。在Javascript中函数即是一般意义的函数,同时 一个货真价实的对象。因此,除了包含函数体内的代码,作为一个对象它还可以拥有其他的属性。除此之外它还有一种特别的能力,那就是作为构造函数来创建新对象。

function Cat(name, age){
   this.name = name;
   this.age = age;
}																																      Cat("xiaoqi",1);

当函数Cat作为一般的函数来调用时,它确实如它自己所描述那样,改变了this所指对象的两个属性而已。 同时函数Cat也是一个对象,用于一些基本的属性例如:call,apply,prototype等等一些从Object继承过来的重要属性,除此之外还可以增加、删除和修改它的属性。因此上面的代码也替换为:

Cat.call(this,["xiaoqi", 1]);

到目前为止,Cat函数已经身兼数职了,即是函数又是对象的,然后它的能力还不止这些:

特殊的函数--构造函数

所谓的特殊函数,完全是唬人的说法。Cat函数本身就是一个构造函数,它的写法和一般的函数并无二致,差别在于我们如何调用它:

function Cat(name, age){
   this.name = name;
   this.age = age;
}

var cat = new Cat("xiaoqi", 1);

熟悉Java的肯定对最后一行new 关键字非常熟悉,但是这里却没有对应class Cat的定义哦, 看来所有的奥妙全都在这个Cat函数里。 我们知道了Javascript有原型模板,也知道一切对象的模板是Object对象,而且Cat函数会自动继承Object,那么这个构造函数就可以以Object为模板来创建一个新的对象。此时,this就不再是指向调用的函数,而是指向新创建的对象。因此,我们可以在构造函数定义更多的属性给Cat:

function Cat(name, age){
   this.name = name;
   this.age = age;
   this.play =function(){
   }
}

var xiaoqi = new Cat("xiaoqi",1);
var daqi = new Cat("daqi",2);
xiaoqi.play(); 
daqi.play();

因此用function来表示一个类型的写法,如果不考虑访问级别的话,甚至比Java这种需要多写一行class更为简洁明了, 当然Javascript并不想要变成Java的样子,也无法替代Java。接下来我们继续讨论面向对象的另一个重要特性,继承

通过prototype属性来实现继承

假如已有一个构造函数:

function Animal(){
	this.run= function(){
	}
}

那么我们在创建一下具体的Animal类型时,例如Cat,就希望能够通过继承的方式run来添加这Animal中的。Javascript是通过prototype属性来实现:

function Cat(name, age){
   this.name = name;
   this.age = age;
}

Cat.prototype = new Animal();
Cat.prototype.constructor = Cat;
var cat =new Cat("xiaoqi",1);
cat.play();

实际上,要理解为什么Cat.prototype 可以实现继承,还要先看看在调用Cat.prototype = new Animal(); 时,到底发生了什么?

先看一个简单的构造函数:

function Simple(){
}
//这段代码相当于:
var Simple = new Function("//body");
首先Simple是类型Function的一个实例,Simple默认就继承了Function.prototype中的所有属性,说明使用new调用构造函数时,不仅调用函数体来初始化,而且把Function.prototype所指对象拷贝到新的实例。 

Simple是一个构造函数,因此可以继续构造基于Simple的实例:

var simple = new Simple();

simple是一个Simple的实例,在Simple构造函数体内并未有任何初始化代码,所有simple的所有属性都来自于Simple.prototype.  而Simple.prototype是默认从Object.prototype过来的。 也就是任何一个Function实例的prototype属性都来自于Object.prototype。

总结一下就是:任何一个构造函数在通过new调用时,除了函数体内的初始化代码外,同时也把prototype上所指的对象拷贝到新实例。如果新实例是一个Function实例,那么它将默认从Object中继承prototype属性。


实现javaScript对象的"继承"的两种方法(prototype与闭包)

实现javaScript对象的"继承"的两种方法(prototype与闭包)
  • canot
  • canot
  • 2016年02月28日 16:13
  • 1290

[JavaScript]构造函数中定义prototype的异常现象及研究

文章结构prototype正常的定义方式构造函数中定义prototype的异常现象(benz instanceof Car) 为false 问题benz.printHistory is not a f...
  • sodino
  • sodino
  • 2016年05月05日 22:14
  • 3383

JS----构造函数与原型prototype 区别

构造函数方法很好用,但是存在一个浪费内存 通过原型法分配的函数是所有对象共享的. 通过原型法分配的属性是独立.-----如果你不修改属性,他们是共享...
  • damys
  • damys
  • 2015年07月22日 17:16
  • 1940

js中的prototype和基于prototype的继承总结

与其他编译语言的继承相比,javascript也有一套继承实现方式,即使用prototype原型及其链的方式。1、我们先用一个简单的例子先理解原型链, (http://img.blog.csdn.n...
  • houyaowei
  • houyaowei
  • 2016年05月18日 15:00
  • 193

JavaScript原型的工作原理(以及如何利用它来实现类的继承)

在上一篇文章里,我们以及详细分析过构造函数,还有怎样将其变成面向对象语言里的类。但是JavaScript不是基于类的编程语言,它是基于原型的编程语言。这到底是什么意思呢?简单来说,JavaScript...
  • zlxadhkust
  • zlxadhkust
  • 2014年04月27日 17:41
  • 1171

javascript中继承(二)-----借用构造函数继承的个人理解

上次博客跟大家分享了自己对原型链继承的理解,想看的同学欢迎猛击这里,上次说到原型链继承有一些问题,主要是两方面的。我们举个栗子来说明下: Q1:共享的超类属性能被任何实例改写,这个是很危险的!看下面...
  • ladycode
  • ladycode
  • 2016年04月29日 16:12
  • 1569

JavaScript的模块化:继承(原型)、封装(闭包)、多态

JavaScript的模块化:继承(原型)、封装(闭包)、多态   一、封装:   封装是实现面向对象程序设计的第一步,封装就是将数据或函数等集合在一个个的单元中(我们称...
  • wustzbq0713
  • wustzbq0713
  • 2015年06月06日 12:48
  • 1053

C++继承中关于子类构造函数的写法

转载于:http://www.cnblogs.com/kaige/p/cplusplus_virtual_inheritance_derived_class_constructor.html 构造方法...
  • shmilxu
  • shmilxu
  • 2016年03月08日 16:42
  • 1017

js 构造函数(construction)与原型(prototype)

1.js原型 java有class和instance,js只有构造函数(function Cat(name,age){this.name=name;this.age=age}),为了实现数据共享和抽象...
  • tang7837010
  • tang7837010
  • 2014年12月24日 11:21
  • 1010

JavaScript中数组Array.prototype的常用的方法总结

Array构造函数的API,我们可以通过控制台打印Array.prototype可以知道有以下这些方法。这是Array的原型对象的所有方法,对数组而言是可以继承所有的这些方法的: 接下来,我们就以12...
  • SpicyBoiledFish
  • SpicyBoiledFish
  • 2017年04月26日 11:40
  • 461
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:Javascript构造函数和prototype实现封装继承
举报原因:
原因补充:

(最多只允许输入30个字)