zoukankan      html  css  js  c++  java
  • 面向对象(OOP)--OOP基础与this指向详解

      前  言

              

     学过程序语言的都知道,我们的程序语言进化是从“面向机器”、到“面向过程”、再到“面向对象”一步步的发展而来。类似于汇编语言这样的面向机器的语言,随着时代的发展已经逐渐淘汰;而面向过程的语言也只有C语言老大哥依然坚挺;现在主流的语言(例如Java、C++、PHP等)都是面向对象的语言。 而我们的JavaScript语言,恰恰介于面向过程与面向对象之间,我们称它为“基于对象”的语言。但是,JS中的OOP依然是我们学习JS的重要一环,当然像“继承”“封装”这样的面向对象特征,都是由模拟实现的。今天,我们就一起来探讨一下JS中的面向对象吧!


    一、OOP基础知识


    1类和对象

    面向对象编程(OOP)  思维导图

    1、类:

        一类具有相同的特征(属性)和行为(方法)的集合。
          eg:人类--> 属性:身高、性别; 方法:吃饭、说话
    2、对象:

        从类中拿出具有确定属性值和方法的个体。
          eg:张三--> 属性:身高:170、 体重;50kg; 方法: 说话-->我叫张三,身高170

    3、类和对象的关系
          类是抽象的,对象是具体的。 (类是对象的抽象化,对象是类的具体化)
          类是一个抽象的概念,只能说类属性和方法,但是,不能给属性赋具体的值
            比如:人类有姓名,但是不能说人类的姓名叫什么。。。。
          对象是一个具体的个例,是将类中的属性进行具体赋值而来的个体。
            比如:张三是人类的一个个体,可以说张三的姓名叫张三。也就是,张三对人类的每一个属性进行了具体的赋值,那么张三就是由人类产生的一个对象。

    4、使用类和对象的步骤:
      ① 创建一个类(构造函数):类名必须使用大驼峰法则。即,每个单词的首字母都要大写,

    function 类名(属性值1,属性值2,...){
        this.属性1 = 属性值1;
        this.属性2 = 属性值2;
        ...
        this.方法 = fucntion(形参){
            //方法中要调用自身属性必须使用thi.属性
        }
    }        


      ② 通过类,实例化(new)出一个对象:

    var obj = new 类名(属性值);
    obj.属性;    //调用属性
    obj.方法(); //调用方法



      ③ 注意事项:
           1、通过类名,new出一个对象的过程,叫做"类的实例化";

             2、类中的this,会在实例化的时候指向新new出的对象。
              所以,this.属性、 this.方法 实际上是将属性和方法绑定在即将new出的对象上面;

           3、在类中,要调用自身的属性,必须使用this.属性。如果,直接使用变量名,则无法访问对象的属性。

           4、类名必须使用大驼峰法则,注意与普通函数的分。
    5、两个重要属性
        ① constructor :返回当前 对象 的构造函数。
         

     zhangsan.constructor == Person; √


        ② instanceof :检测一个对象是不是一个类的实例;

    lisi instanceof Person          √ lisi是通过Person类new出的
    lisi instanceof Object           √ 所有对象都是Object的实例
    Person instanceof Object     √ 函数本身也是对象



    6、广义对象与狭义对象:
      ① 狭义对象:只有属性和方法,除此之外没有任何其他内容;

    var obj = {};
    var obj = new Object();




      ② 广义对象: 用字面量声明的基本数据类型不是对象,不能够添加属性和方法
        除了用字面量声明的基本数据类型外JS中万物皆对象。换句话说,只要能够添加属性和方法的变量,都可以称之为对象。

    var s = "12"; //不是对象
    s.name = "aaa";
    console.log(typeof(s)); //string
    console.log(s.name);    // undefined 字面量声明的字符串不是对象,不能添加属性
    
    var s = new String("123"); //是对象
    s.name = "aaa";
    console.log(typeof(s)); //object 
    console.log(s.name);    // aaa 使用new关键字声明的字符串是对象,能添加属性和方法

    2OOP的属性和方法

    成员属性和成员方法

    1、在构造函数中,使用this.属性声明,或者在实例化出对象以后,使用"对象.属性"追加的,都属于成员属性或成员方法。也叫实例属性和实例方法
      成员属性/成员方法: 是属于由类new出的对象的。
      需要使用"对象名.属性名"调用.

    私有属性和私有方法

    2、通过"类名.属性名"、"类名.方法名"申明的属性和方法,称为静态属性、静态方法 。也叫类属性和类方法;
        类属性/类方法,是属于类的(属于构造函数)。
        通过"类名.属性名"调用
    3、成员属性是属于实例化出的对象的,只能使用对象调用;
        静态属性是属于构造函数的,只能使用类名调用。

    私有属性和私有方法

    4、在构造函数中使用var申明的变量称为私有属性,使用function申明的函数称为私有方法

    function Person (){
      var num = 1 ; //私有属性
      function func(){}    //私有方法
    }

    私有属性和私有方法的作用域,只在构造函数中有效。即,只能在构造函数内部使用,在构造函数外部,无论使用对象还是类名都无法调用。

     
    代码解释
     
    function Person(name){
                    this.name = name;                //声明成员属性
                    var sex = "男";             //私有属性
                    this.sayTime =  function(){      //声明成员方法
                        alert("我说当前时间为"+getTime());
                    }
                    this.writTime =  function(){
                        alert("我写了当前时间为"+getTime());  //调用私有方法
                    }               
                    function getTime(){                //私有方法
                        return new Date;
                    }
           }
      /***************************成员属性/方法*************************/ var zhangsan = new Person("张三");      //类的实例化 zhangsan .age = 18;      //追加成员属性 alert(zhangsan .name);    //调用成员属性 /***************************静态属性/方法***************************/ Person.count = "60亿"; //声明静态属性 alert(Person.count); //调用静态属性 var lisi = new Person("李四"); alert(lisi.count); //undefined 静态属性是属于类的,只能用类名调用 /*************************私有属性/方法**************/ lisi.sayTime(); //外部间接调用 lisi.writTime();


    2  this指向详解

    1、相关知识:

    对于判断this的指向问题,总的来说,就是:谁最终调用函数,this就指向谁。


      ① this指向谁,不应该考虑函数在哪声明,而应该考虑函数在哪调用;
      ② this指向的永远只可能是对象,而不可能是函数;
      ③ this指向的对象,叫做函数的上下文(context),也叫函数的调用者。

    2、虽然知道了,谁最终调用函数,this就指向谁。但是,还是觉得有点笼统,不够详细。对this的指向问题还是太模糊。

    于是,在这里,影子特向大家介绍,this指向问题规律的5条通用判断方法。

      ① 通过 函数名() 调用的,this永远指向window;
      ② 通过 对象.方法 调用的,this指向该对象;
      ③ 函数作为 数组 中的一个元素,用数组下标调用的,this指向该数组;
      ④ 函数作为Window内置函数的 回调函数 使用,this指向window;
        setInterval、 setTimeout
      ⑤ 函数作为构造函数,使用 new关键字 调用,this指向新new出的对象。

    下面,将对每条规律,做出案例,以供大家,理解:

    <div id="div1"style=" 200px;height: 200px;background-color: red;">
                这是一个div
    </div>
    function func(){
                console.log(this);
            }
            var obj ={
                func : func
            }
            function func1(){
                func();        //this指向Window
            }
            //① 通过  函数名()  调用的,this永远指向window;
            func();            //this指向Window
    //② 通过 对象.方法 调用的,this指向该对象; obj.func(); //this指向对象obj window.onclick = function(){ document.getElementById("div1").onclick = function(){ func(); // 最终还是使用()调用,所有指向window } document.getElementById("div1").onclick = func;//广义对象,指向div1 } //③ 函数最为数组中的一个元素,用数组下标调用的,this指向该数组 var arr = [1,2,3,func,4,5]; arr[3](); //④ 函数作为Window内置函数的回调函数使用,this指向window; setTimeout(func,1000); //⑤ 函数作为构造函数,使用new关键字调用,this指向新new出的对象。 var obj1 = new func();

    下面是一个影子总结的一个综合案例:

            /************************综合案例****************/
            var obj1 = {
                name : "obj1",
                arr : [func, 1,{name : "obj2",func : func},3,4],
            }
            obj1.arr[0]();                        //最终的调用者是数组,this指向数组
            setTimeout(obj1.arr[0],1000);        //obj1.arr[0仅仅是取到函数func,但并没有调用。函数的最终调用者是setTimeout,指向window;这个式子相当于setTimeout(func,1000);
            setTimeout(obj1.arr[2].func,1000);    //函数的最终调用者是setTimeout.原因同上↑
            obj1.arr[2].func();                    //最终的调用者是{name : obj2,func : func},this指向{name : obj2,func : func}
            

    好了,今天影子给大家分享的东西就这么多了。最后,影子这里还有一道this指向的题,就一这道题结束今天的分享吧。至于答案就留到下次。哈哈。。。

    var fullname = 'John Doe';
            var obj = {
               fullname: 'Colin Ihrig',
               prop: {
                  fullname: 'Aurelio De Rosa',
                  getFullname: function() {
                     return this.fullname;
                  }
               }
            };

    console.log(obj.prop.getFullname());
    //?? var test = obj.prop.getFullname; console.log(test()); //?? obj.func = obj.prop.getFullname; console.log(obj.func());
          //??? var arr = [obj.prop.getFullname,1,2]; arr.fullname = "JiangHao"; console.log(arr[0]()); console.log(arr[0]);
          //????
  • 相关阅读:
    java使用jsp servlet来防止csrf 攻击的实现方法
    Fiddler抓包6-get请求(url详解)
    Fiddler抓包5-接口测试(Composer)
    Fiddler抓包4-工具介绍(request和response)
    Fiddler抓包3-查看get与post请求
    Selenium2+python自动化60-异常后截图(screenshot)
    Selenium2+python自动化59-数据驱动(ddt)
    Selenium2+python自动化58-读取Excel数据(xlrd)
    Selenium2+python自动化57-捕获异常(NoSuchElementException)
    Selenium2+python自动化56-unittest之断言(assert)
  • 原文地址:https://www.cnblogs.com/2502778498spw/p/7667744.html
Copyright © 2011-2022 走看看