zoukankan      html  css  js  c++  java
  • javascript关于面向对象的总结

    对于javascript大家大部分时间用来做效果,但却忽视了最基础的东西,
    当大家把javascript基本功学扎实了,我认为对以后写出漂亮的js代码有很大的帮助,
    今天就总结下我对javascript关于面向对象方面的理解
    首先总结一下javascript中的"类",
    第一种算是比较灵活的方式了,成为工厂定义方式

    var obj=new Object;
    obj.color='red';
    obj.dodo=function(){...};

    为什么说它灵活,就是因为它可以在实例化对象后,可以对该对象增加属性,可以完善我们的需求,
    我们经常会得到实例化的对象比如:=var aa=document.getElementById('lover'),此时我们可以很方便的增加各种方法属性,
    aa.onclick=function(){...};aa.lover='i love you ';等,以至传递的时候只需要传递该对象;
     

    <script   language= "javascript">
    var obj=new Object;
    obj.color='red';
    obj.dodo=function(){alert('aa')};

    for(aa in obj)
    {
    alert(aa);//color;dodo;
    }
    </script>

    javascript中定义类我们平时都是按照这种方式,因为毕竟和java和c#比较接近,

    function Car(scolor,snum)
    {
    this.color=scolor;
    this.dodo=function(){alert('aa')};
    }
    //这叫做构造函数方式定义类
    var obj=new Car('yellow',30);
    for(aa in obj)
    {
    alert(aa);//color;dodo
    }

    上面不用多介绍大家是最熟悉的了,

    接下来介绍原型方式:
    什么是原型,关于具体的概念大家可以查看资料,不想说太多,只想举例子来说明,
     

    <script   language= "javascript">
    function Car(scolor,snum)
    {
    this.color=scolor;
    this.dodo=function(){alert('aa')};
    }
    Car.prototype.getValue = function (){
    return this.color;
    }

    Car.prototype.setValue = function (value){
    this.color = value;
    }
    var obj=new Car('yellow',30);
    obj.setValue(666);
    alert(obj.getValue());//666
    for(aa in obj)
    {
    alert(aa);//color;dodo;setValue;getValue
    }
    </script>

    可以看到利用原型可以为对象增加属性和方法,具体为什么要利用原型来操作,概念性的问题可以查资料,
    但是有一点需要注意的是:

    <script   language= "javascript">
    function Car(scolor,snum)
    {
    //this.cc="cc";
    //this.docc=function(){alert(this.cc)}
    }

    Car.prototype.cc = "cccc"
    Car.prototype.docc = function (){alert(this.cc)}

    var obj=new Car('yellow',30);
    for(aa in Car.prototype)
    {
    alert(aa);//cc;docc
    }
    alert(obj.cc);
    obj.docc();
    </script>

    虽然同样是给对象增加了cc属性和docc方法,但是查找顺序是先查找构造函数中是否有该属性和方法,
    没有再搜索propertype,根据

    <script   language= "javascript">
    function Car(scolor,snum)
    {
    this.cc="cc";
    this.docc=function(){alert(this.cc)}
    }

    Car.prototype.cc = "cccc"
    Car.prototype.docc = function (){alert(this.cc)}

    var obj=new Car('yellow',30);
    alert(obj.cc);//cc
    delete obj.cc;
    alert(obj.cc);//cccc

    obj.docc();//cccc
    delete obj.docc();
    obj.docc();//cccc
    </script>

    可以看到首先删除两个属性仍然可以输出属性值,并且第一个obj.docc()获取的是原型中的cc属性值

    看下面的例子:
     

    <script   language= "javascript">
    function Car(scolor,snum)
    {
    this.cc="cc";
    }

    Car.prototype.cc = "cccc"
    Car.prototype.docc = function (){alert(this.cc)}

    var obj=new Car('yellow',30);
    Car.prototype.docc();//cccc
    </script>

    可以直接调用原型方法,调用的是原型中的cc属性而不是构造函数的,
    如果没有定义原型cc属性,就会显示undefined,在直接调用原型方法时这是需要注意的地方
    再然后介绍一下javascript静态的实现方法:

    <script   language= "javascript">
    function Car()
    {
    Car.docc = function (){alert('cc')}
    }

    Car.docc = function (){alert('cccc')}

    Car.docc();//cccc
    var obj=new Car();//初始化后构造函数中的静态方法覆盖外边定义的静态方法,需要注意!
    Car.docc();//cc
    </script>

    在了解以上基本概念以后,接下来介绍一下javascript如何实现继承,
    我们知道所有的对象都是继承objec类,而javascript中是怎样继承了object类呢?
    其实在javascript中隐藏了

    Car.prototype = new Object();
    作用是什么呢?很明显Object中有toString()方法,
    这样

    Car.paopertype.toString()=function(){...}
    //是不是就显而易见了,在实例化Car可以成功的引入该属性,而Object中的所有属性和方法都归了Car,就这样Car继承了Object的所有属性和方法。
    <script   language= "javascript">
    function Car(scolor,snum)
    {
    this.cc="cc";
    }

    alert(Car.toString());
    </script>
    上面的例子不是太贴切,我补充一个大家看看


    <script   language= "javascript">

    function obj()
    {
    this.aa='aa';
    this.bb=function(){alert('==========')};
    }

    function Car()
    {
     this.cc="cc";
    }

    Car.prototype = new obj();
    var aa=new Car();
    for(a in aa)
    {
    alert(a);//aa;bb;cc
    }
    aa.bb();
    for(b in Car.prototype)
    {
    alert(b);//aa;bb
    }
    </script>
    这样大家就能明白

    Car.prototype = new obj();
    这句话的含义了。

    接下来又引出一个重要属性,constructor,


    <script   language= "javascript">
    function Car(scolor,snum)
    {
    this.cc="cc";
    }

    alert(Car.prototype.constructor);//constructor就是指向自己本身的一个属性
    </script>


    再看下面

    <script   language= "javascript">
    function Car(scolor,snum)
    {
    this.cc="cc";
    }

    Car.prototype.cc = "cccc"
    Car.prototype.docc = function (){alert(this.cc)}

    alert(Car.prototype.constructor.prototype.cc);//cccc
    Car.prototype.constructor.prototype.docc();//cccc
    alert(Car.prototype.constructor===Car);//true
    </script>

    大家看结果明白了吧

    还有让大家比较头疼的问题就是call和apply的用法,
    首先给大家做个解释,

    function classA(scolor){
    this.docc=function(){...}
    }

    function classB(){
    //this.newMethod=classA;
    //this.newMethod(scolor);
    //delete this.newMethod();
    //这三行与下面的call是一个效果,通过这个例子大家就应该明白call具体是怎样执行的了,等同于上面三行的实现,
    一句this.newMethod(scolor);函数调用,就将classA中的关于this.的方法和属性就都归classB,因为此时classA中的
    this指针在classB内部指向的就是classB本身,所以这也是实现继承的一种手段,
    classA.call(this,scolor);
    }

    完整的例子:

    <script   language= "javascript">
    function classA(scolor){
    this.cc=scolor;
    this.docc=function(){alert(this.cc)}
    }

    function classB(){
    classA.call(this,"yellow");
    }

    var obj=new classB();
    alert(obj.cc)//yellow
    obj.docc();//yellow
    </script>

    此时大家想原型方法能够继承吗?其实就按照我上面的解释,大家也该明白函数调用this.newMethod(scolor)只调用函数本身,就象我们平时使用函数一样,不会牵扯到原型上去,所以

    <script   language= "javascript">
    function classA(scolor){
    this.cc=scolor;
    this.docc=function(){alert(this.cc)}
    }

    classA.prototype.dd = "dddd"
    classA.prototype.dodd = function (){alert(this.dd)}

    function classB(){
    classA.call(this,"yellow");
    }

    var obj=new classB();
    alert(obj.dd)//undefined
    obj.dodd();//出错没有该方法
    </script>


    那我们怎么办呢?很简单,只要仔细看了我上面的介绍,

    <script   language= "javascript">
    function classA(scolor){
    this.cc=scolor;
    this.docc=function(){alert(this.cc)}
    }

    classA.prototype.dd = "dddd"
    classA.prototype.dodd = function (){alert(this.dd)}

    function classB(){
    }
    classB.prototype = new classA("yellow");
    var obj=new classB();

    alert(obj.cc)//yellow
    obj.docc();//yellow

    alert(obj.dd)//dddd
    obj.dodd();//dddd
    </script>

    我再给大家举个合用的例子

    <script   language= "javascript">
    function classA(scolor){
    this.cc=scolor;
    this.docc=function(){alert(this.cc)}
    }

    classA.prototype.dd = "dddd"
    classA.prototype.dodd = function (){alert(this.dd)}

    function classB(){
    classA.call(this,"red");//初始化red后继承
    }
    classB.prototype = new classA("yellow");//初始化yellow后继承
    var obj=new classB();

    alert(obj.cc)//red
    obj.docc();//red

    alert(obj.dd)//yellow
    obj.dodd();//yellow
    </script>

    为什么会是red不是yellow原因很简单,一个是在构造函数内实现了继承,一个是原型继承,而我们说过构造函数在
    原型之前调用,所以会出现red而不是yellow。

    最后借助风之石写的一个例子结束此次文章:

    <html>
    <body>
    <button id=btTest>test</button>
    </body>
    </html>
    <script>
    if(!document.all){
        HTMLElement.prototype.attachEvent=function(sType,foo){
            this.addEventListener(sType.slice(2),foo,false)
        }
    }
    Function.prototype.bindNode=function(oNode){
        var foo=this,iNodeItem
        //使用了全局数组__bindNodes,通过局部变量iNodeItem进行跨函数传值,如果直接传送oNode,也将造成闭包
        if(window.__bindNodes==null)
            __bindNodes=[]
        __bindNodes.push(oNode)
        iNodeItem=__bindNodes.length-1
        //释放oNode
        oNode=null
        return function(e){
            foo.call(__bindNodes[iNodeItem],e||event)
                 //需要注意的是调用了call本身就是一个调用了foo()函数的过程,所以上面返回的是一个函数
        }
    }
    abc()
    function abc(){
        var bt=document.getElementById("btTest")
        bt.attachEvent("onclick",function(){
            //如果不经过bindNode处理,下面的结果将是undefined
            alert(this.tagName)
        }.bindNode(bt))
        //释放bt
        bt=null
    }
    </script>
    大家可以自己回味一下call的用法,不明白或者有错误可以在回复中指出,匆匆忙忙写完一定会有不足之处,
    请指教


    本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/xiaolei1982/archive/2008/10/02/3010066.aspx

  • 相关阅读:
    forceStopPackage与killBackgroundProcesses方法
    github上十二款最著名的Android播放器开源项目
    AndroidStudio编译错误:Error: null value in entry: blameLogFolder=null
    Vue相关开源项目库汇总 http://www.opendigg.com/tags/front-vue
    Android Drawable 那些不为人知的高效用法
    Android数据存储
    touch事件的分发机制
    Hybrid 开发
    关于Http协议
    设计原理+设计模式
  • 原文地址:https://www.cnblogs.com/jazzka702/p/1503250.html
Copyright © 2011-2022 走看看