zoukankan      html  css  js  c++  java
  • JavaScript面向对象编程(二)构造函数和类

    new关键字和构造函数

    在文章JavaScript面向对象编程(一)原型与继承中讨论啦JavaScript中原型的概念,并且提到了new关键字和构造函数。利用new关键字构造对象的实例代码如下:

     1 //define a constructor
     2 var Func = function(name,id){
     3      this.name = name;
     4      this.id = id;
     5  }
     6  Func.prototype.className = "Func"
     7  var obj = new Func("obj",1);//{name: "obj", id: 1, className: "Func"}
     8  obj.hasOwnProperty("name");//true
     9  obj.hasOwnProperty("id");//true
    10  obj.hasOwnProperty("className");//false

    new Func()生成一个对象,用跟在new后面的函数Func对所生成的对象进行初始化,并且将Func.prototype作为所生成对象的原型。在Func函数中的this指向的就是new所生成的对象,代码的第3和第4行是给这个对象添加两个属性name和id。在第6行中,给Func.prototype添加了属性为className,因为Func.prototype是所生成对象obj的原型,所以可以从obj中访问className的值。因为className属性是从原型Func.prototype中访问的,所以obj.hasOwnProperty("className")===false。

    这样以来,就生成了一个原型链:obj->Func.prototype.

    需要注意的是,构造函数中通过this.name给对象添加了属性,这个name属性将是生成对象所拥有的。虽然JavaScript没有强调类的概念,但是从某种意义上,定义了构造函数即是定义了类。构造函数是类的公共标识[1]。

    constructor属性

    每个JavaScript函数都自动拥有prototype属性,这个属性的值是一个对象(prototype属性的值可以被重新赋值)。prototype对象中包含一个属性,名为constructor。

    1 Func.prototype.constructor === Func;//true
    2 obj.constructor === Func;//true

    可以看到,构造函数预定义的(可以重新赋值)prototype中的constructor属性是函数本身。因为new所构造的对象以Func.prototype为原型,所以也可以从obj中访问constructor属性。调用obj.constructor可以重新对obj进行“构造”。

    1 obj.constructor("new name",2);//{name: "new name", id: 2, className: "Func"}

    obj.constructor就是Func,因此Func中的this.name = name;this.id = id;重新对obj的属性进行了赋值。(初次使用new Func("obj",1)时因为对象没有name和id属性,所以是给对象添加属性)。

    instanceof 运算符

    1 obj instanceof Func//true

    运算符可以判断obj是否以Func.prototype 为原型。需要注意的是,只需要以Func.prototype 为原型即可,不一定需要通过new关键字构造。如:

    1 var obj2 = Object.create(Func.prototype);
    2 obj2 instanceof Func//true

    “继承”类

    上文提到,定义了构造函数即是定义了类。并且将构造函数的prototype属性作为所构造的对象的原型。那么,如果用另外一个构造函数生成的对象给构造函数的prototype属性赋值,就可以在原型链中再添加一个节点,达到类继承的效果。

     1 //a function which is used to generate a derived class
     2 var inheritClass = function(baseClass){
     3     if( typeof baseClass === "function"){
     4         var derivedClass = function(){};
     5         derivedClass.prototype = new baseClass();
     6         derivedClass.prototype.constructor = derivedClass;
     7         return derivedClass;
     8     }
     9     else{
    10         throw TypeError();       
    11     }
    12 }
    13 //define the base class
    14 var TransportTool = function(){};
    15 TransportTool.prototype.accelerate = function(){
    16         console.log("speed up!");
    17 };
    18 //define a derived class
    19 var Plane = inheritClass(TransportTool);
    20 Plane.prototype.rise =  function(){
    21         console.log("rise up!");
    22 };
    23 //define the object
    24 var thePlane = new Plane();
    25 thePlane.accelerate();
    26 thePlane.rise();

    上述代码中首先定义了一个函数inheritClass用于生成一个派生类。首先在代码的第5行将derivedClass的prototype赋值为new baseClass。这样一来就在原型链中加了一个节点:实例对象->derivedClass.prototype->baseClass.prototype。代码第6行derivedClass.prototype.constructor设置为derivedClass。因为第5行将derivedClass预设的prototype值修改了,所以在第6行之前derivedClass.prototype.constructor === baseClass。这不符合一个类的行为,所以要将其值修改。修改之后,对象thePlane.constructor === Plane,是make sense的。

    thePlane是派生类Plane的实例,也是TransportTool的实例,原因是原型链为thePlane ->Plane.prototype->TransportTool.prototype

    1 thePlane instanceof Plane//true
    2 thePlane instanceof TransportTool//true

    因为原型链的作用,thePlane可以同时进行“accelerate”和“rise”操作。

    总结

    主要从理论角度讨论了JavaScript的面向对象编程的方法,就是基于原型链。new操作符可以将构造函数的prototype属性作为所构造的函数的原型。派生的构造函数的prototype属性可以以另一个构造函数的prototype属性作为原型,形成了原型链。这就是类的“继承”。既然理论已经介绍了,那么接下来的文章JavaScript 面向对象编程(三)如何写类和子类

    会介绍如何用JavaScript进行面向对象编程,如何模拟传统的类、成员、静态成员等。

    参考文献

    1)《JavaScript:The Definitive Guide》第六章,第九章

    2)JavaScript的大师的个人博客:http://javascript.crockford.com/prototypal.html

    3)将JavaScript OOP介绍的很好的文章:http://phrogz.net/JS/classes/OOPinJS2.html

    4)JavaScript Garden:http://bonsaiden.github.io/JavaScript-Garden/

    5)介绍原型及原型链的文章:http://blog.vjeux.com/2011/javascript/how-prototypal-inheritance-really-works.html

  • 相关阅读:
    Android中@id与@+id区别和sharedUserId属性详解*
    Android应用的安全的攻防之战
    Android动态方式破解apk进阶篇(IDA调试so源码)
    Android动态方式破解apk前奏篇(Eclipse动态调试smail源码)
    Android动态方式破解apk终极篇(加固apk破解方式)
    Android中插件开发篇之----动态加载Activity(免安装运行程序)
    Android中插件开发篇之----应用换肤原理解析
    Android中插件开发篇之----类加载器
    Android中的动态加载机制
    Android 编程下Touch 事件的分发和消费机制和OnTouchListener,OnClickListener和OnLongClickListener的关系*
  • 原文地址:https://www.cnblogs.com/zhenchaoni/p/JavaScript_constructor_class.html
Copyright © 2011-2022 走看看