面向对象笔记一

js 面向对象的基本概念和基本使用方法

  1. -> js 是不是一个面向对象的语言(众说纷纭)?

    • 不是:与传统面向对象的理论语言有矛盾。C#,Java。
    • 是:js里面到处都是对象,数组,时间,正则... 和 DOM。也可以像传统面向对象的语言那样用 new 的方式创建对象
  2. -> js是一个基于对象多范式编程语言
    • 面向过程的方式
    • 面向对象的方式
    • 函数式 递归与链式 例: Jquery 链式编程
    • 比如: 给 div 标签添加样式
             $( ‘div‘ ).css( ‘border‘, ‘1px solid red‘ )
                       .css( ‘width‘, ‘400px‘ )
                       .css( ‘height‘, ‘200px‘ );
      

面向对象的概念

对象的定义:无序属性的集合,其属性可以包含基本值,对象或是函数

  1. 面向:将脸朝向... -> 关注对象,用对象
  2. 面向过程 -> 使用过程的方式开发
    • 关注过程,步骤,细节,顺序。 事无巨细,亲自为之
  3. 面向对象开发 -> 使用对象的方式开发
    • 要做什么,找到对象,告诉他做,等结果
  4. 面向对象不是面向过程的替代,是面向过程的封装,可以理解为面向对象编程就是面向编程的一种简化

万物皆对象

  • 在实际开发中,对象是一个抽象的概念,可以简单理解为: 数据集或功能集。可以混合使用

    • 数据集: 很多数据打包到一起。 { name: ‘张三‘, age:19, gender:‘男‘ }

      • 假设展示 10 个商品数据,每个商品有名字,描述,价格,图片等
      • 对象可以用来保存数据,每一个商品可以变成对象 { name: ‘123‘, desc:‘123‘, price: 0 }
      • 引入数组,将多个对象数据存储在数组中(数组也是对象)
    • 功能集(函数集,方法集)
    • 在 js 中,所谓的对象就是 键值对 的集合
  • 给页面中所有的div和p添加边框,设置宽高

    <body>
      <!-- 给页面中所有的div和p添加边框,设置宽高 -->
      <div>div1</div>
      <p>p标签</p>
      <div>div2</div>
    </body>
    <script>
      /* 获得所有div */
      var divs = document.getElementsByTagName(‘div‘);
      var ps = document.getElementsByTagName(‘p‘);
      /* 设置样式 */
      /* 由于 getby 获取的是 伪数组 */
      for ( var i = 0; i < divs.length; i++ ) {
          divs[ i ].style.border = ‘1px solid red‘;
          divs[ i ].style.width = ‘300px‘;
          divs[ i ].style.height = ‘200px‘;
      }
      for ( var i = 0; i < ps.length; i++ ) {
          ps[ i ].style.border = ‘1px solid blue‘;
          ps[ i ].style.width = ‘300px‘;
          ps[ i ].style.height = ‘200px‘;
      }
    </script>
    
  • 利用函数封装较长的功能
    <script>
     /* 利用函数封装较长的功能 */
      function tag ( tagName ) {
          return document.getElementsByTagName( tagName );
      }
      var divs = tag(‘div‘);
      var ps = tag(‘p‘);
    
      for ( var i = 0; i < divs.length; i++ ) {
          divs[i].style.border = ‘1px solid red‘;
          divs[i].style.width = ‘300px‘;
          divs[i].style.height = ‘200px‘;
      }
      for ( var i = 0; i < ps.length; i++ ) {
          ps[i].style.border = ‘1px solid blue‘;
          ps[i].style.width = ‘300px‘;
          ps[i].style.height = ‘200px‘;
      }
    <script>
    
  • 封装函数进行循环
    <script>
      function tag ( tagName ) {
          return document.getElementsByTagName( tagName );
      }
      function addCss( array, border, width, height ) {
          for( var i = 0; i < array.length; i++ ) {
              array[i].style.border = border;
              array[i].style.width = width;
              array[i].style.height = height;
          }
      }
      var divs = tag( ‘div‘ );
      var ps = tag(‘p‘);
      addCss( divs, ‘1px solid red‘, ‘400px‘, ‘50px‘ );
      addCss( ps, ‘1px solid blue‘, ‘300px‘, ‘50px‘ );
    </script>
    
  • addCss的改良
    <script>
      function tag ( tagName ) {
          return document.getElementsByTagName( tagName );
      }
      function addCss( array, styles ) {
          for( var i = 0; i < array.length; i++ ) {
              for( var k in styles ) {
                  array[i].style[k] = styles[k];
              }
          }
      }
      var divs = tag(‘div‘);
      var ps = tag(‘p‘);
      addCss( divs, {
          ‘border‘: ‘1px solid red‘,
          ‘width‘: ‘400px‘,
          ‘height‘: ‘50px‘
      });
      addCss( ps, {
          ‘border‘: ‘1px solid red‘,
          ‘width‘: ‘400px‘,
          ‘height‘: ‘50px‘
      });
    </script>
    
  • 自己定义的函数越多,那么开发的时候就越方便,但是,也有隐患,自己定义的越多,那么与引入的框架出现冲突的几率就越大,一旦出现名字冲突了,就会造成框架中的功能无法使用。
  • 怎么办? 定义的名字越多,问题的几率越大,最简单的方法就是尽可能少定义名字
  • 定义一个对象,然后所有的函数,变成这个对象的方法即可
    <script>
      var jespon = {
          tag: function( tagName ) {
              return document.getElementsByTagName( tagName );
          },
          addCss: function( array, styles ) {
              for( var i = 0; i < array.length; i++ ) {
                  for( var k in styles ) {
                      array[i].style[k] = styles[k];
                  }
              }
          }
      }
      var divs = jespon.tag(‘div‘);
      var ps = jespon.tag(‘p‘);
      jespon.addCss( divs, {
          ‘border‘: ‘1px solid red‘,
          ‘width‘: ‘400px‘,
          ‘height‘: ‘50px‘,
          ‘background‘: ‘green‘
      });
      jespon.addCss( ps, {
          ‘border‘: ‘1px solid red‘,
          ‘width‘: ‘400px‘,
          ‘height‘: ‘50px‘
      });
    </script>
    

面向对象的特性

  • 抽象性:抽取我们所需要的数据信息等
  • 封装性
  • 继承性
  • (多态性)

名词提炼法找对象

  • 做一个表格排序

    • 面向过程: 1创建表格, 2添加点击事件, 3排序,更新数据
    • 面向对象: 1创建表格对象, 2添加数据

实际开发的时候如果需要完成一个功能

  • 首先考虑系统是否提供了对象

    • 例如: 创建图片: var img = new Image(); img.src = ‘...png‘;
    • 例如: 获取页面元素:document 标签对象
    • 用 document对象 获取导航栏里面的所有li 标签 var nav = document.getElementById( ‘nav‘ ); var lis = document.getElementsByTagName( ‘li‘ );
  • 如果系统没有提供,可以自己定义,或第三方
    <script>
      var jespon = {
          tag: function( tagName ) {
              return document.getElementsByTagName( tagName );
          },
          addCss: function( array, styles ) {
              for( var i = 0; i < array.length; i++ ) {
                  for( var k in styles ) {
                      array[i].style[k] = styles[k];
                  }
              }
          }
          attr: ...,
          getId: ...
      }
    <script>
    

js 的数据类型

  • 基本数据类型(值类型):数字 number,字符串 string,布尔 boolean

    • 基本数据类型的存储模型就是一个方格里面放一个数据
  • 复合数据类型(引用类型):对象(数组,时间类型,函数类型)
    • 复合类型,除了函数其他的数据类型 无法使用 typeof 来获得数据类型名,typeof arr 等 拿到的都是object
    • 需要使用 Object.prototype.toString.apply( )
  • 空类型: null undefined
      var arr = [1, 2, 3];
      console.log( typeof arr );       //object
      console.log( Object.prototype.toString.apply(arr) );  //  [object Array]
    

复合类型的存储模型

  • 复合类型的对象是一个单独的内存区域, 对象有什么属性, 那么内存区域中就有什么数据. 变量 p 只存储该对象的 ‘地址‘. 所以 p 不是真正存储数据的区域.

     // 联想内存逻辑图
     var arr1 = [ 1, 2, 3, 4 ];
     var arr2 = [
         { name: ‘张三‘, age: 19, gender: ‘男‘ },
         { name: ‘李四‘, age: 18, gender: ‘男‘ },
         { name: ‘小李‘, age: 17, gender: ‘女‘ }
     ];
    

值类型和引用类型的存储特征

  • 值类型的数据,只需要开辟一段内存存储数据即可

    var a = 123;
    var b = ‘abc‘;
    var c = true;
    
  • 对象类型(引用类型),对象才是真正的数据,需要占据单独的内存。而变量名只是存储着对象的内存地址(引用)
    • 即创建一个对象,并赋值,需要两块内存空间,一个存储数据(对象)。另一个存储变量以引用对象
    • var o = { name: "张三", age: 19 },前后各占一块空间,前者于栈,后者于堆

值类型与引用类型的赋值与传参的特性

  • 赋值:将原变量中的数据拷贝一份,然后存储到给定变量中

    1. 值类型

       var a = 123; // 有个盒子a,里面存了123
       var b ;        // 有个盒子 b, 里面什么都没有 (undenfied)
       b = a;    // 将 a 中存储的东西赋值一份,然后赋值为 b,即存储在 b 中
      
      • b 和 a 是两个独立的变量, 两者之间不再有关系。
      • 改变其中一个数据,另一个不变。
    2. 引用类型
       var o1 = { num:123 };
       var o2;
       // 赋值
       o2 = o1; //o1 中存储的是引用,或‘地址’
      
      • 将 o1 中存储的内容拷贝一份,存储到 o2 中,o1 和 o2 虽然是不相同的两个变量, 即两个独立的盒子. 但是由于拷贝的内容是地址,存储的地址相同。
      • 在访问数据的时候, o1 与 o2 也是访问同一个数据, o1 将数据修改了, o2 再读取,读取的就是修改后的数据。

函数参数传递

  • 什么是函数参数传递 函数要调用,一般会给函数传递参数 在调用函数的时候,会将参数中表示的数据拷贝一份,然后给参数赋值
  • 值类型传递
      function foo ( num ) {
          console.log( ‘num:‘ + num );    // 123
          num++;
          console.log( ‘num:‘ + num );    // 124
      }
      // 调用
      var a = 123;
      console.log( a );    // 123
      foo( a ); // 调用就是执行,将 a 中存的值,拷贝一份
                // 然后进入 函数 foo
                // 给参数赋值,相当于 num = a;
                // 进入函数体,开始执行函数
      console.log( a );    // 123
    
  • 引用类型传递
      function foo ( num ) {
          console.log( ‘nu====m:‘ + num[ 0 ] );    // 123
          num[ 0 ]++;
          console.log( ‘num:‘ + num[ 0 ] );    // 124
      }
      // 调用
      var a = [ 123 ];
      console.log( a[ 0 ] );    // 123
      foo( a );
      console.log( a[ 0 ] );    // 124
    

    此时的赋值特性与前面介绍的值类型引用类型的赋值是一个特点

深拷贝与浅拷贝

什么是拷贝: 就是创建一个与目标数据一模一样的数据

var p = { name: ‘张三‘ };
var p1 = p;                   // 是否存在拷贝
// 一般描述拷贝是指拷贝对象
p1 = {};
p1.name = p.name;// 才是拷贝

给 对象 p 提供一个 clone 方法, 完成拷贝

  • 浅拷贝:如果对象的属性也是一个引用类型, 拷贝的时候不重新创建一个新的对象来实现该属性的拷贝, 那么就是浅拷贝.即任何不完全的拷贝都是浅拷贝
  • 深拷贝:将两个对象完全从内存中隔离开, 就是深拷贝. 即每一个引用属性, 以及引用属性的引用属性, ... 全部拷贝出来.

构造函数( 构造器 constructor )的作用

构造器:用来创建对象的函数。 js 中对象的动态特性, 即 想要什么属性就可以给什么属性

    var o = {};        // 这时 o 对象没有 name 属性
    o.name = "aaa";    // 这时 o 对象拥有了 name 属性且值为 “aaa”

在 js 中 对象如果没有指定的属性, 只需要利用赋值就 可以给对象 动态 提供该属性.

  • 点语法与关联数组语法

      o.name = ‘jim‘;                // 点语法赋值
      console.log( o.name );        // 点语法取值
      o[ ‘name‘ ] = ‘tom‘;        // 关联数组语法赋值
      console.log( o[ ‘name‘ ] ); // 关联数组语法取值
    
  • 创建一个 Person 对象
      var p = {};        // 什么都没有的对象
      // 根据需要添加成员
      p.name = ‘张三‘;
      p.age = 30;
      p.gender = ‘男‘;
    
  • 简化,提供一个创建 Person 对象的函数
      function createPerson( name, age, gender ) {
          var p = {};
          p.name = name;
          p.age = age;
          p.gender = gender;
          return p;
      }
    
      var p1 = createPerson( ‘jepson‘, 19, ‘男‘ );
      var p2 = createPerson( ‘lucy‘, 18, ‘女‘ );
    

    这个( 这种类型 )的函数就是用来创建对象的, 即生产对象. 常常将这类函数, 称为 ‘工厂函数‘

构造方法创建对象

构造器中不需要 return 语句. 一般也可以不写 调用构造器的时候, 使用 new 运算符引导 在构造器中 this 表示当前对象. 给对象提供成员使用 this.xxx 的 方式

  • 将 createPerson 改造成构造器

      function createPerson( name, age, gender ) {
          this.name = name;
          this.age = age;
          this.gender = gender;
      }
      // 调用构造器创建对象
      var p = new createPerson( ‘jepson‘, 19, ‘男‘ );
    
  • 构造器创建对象的本质: 还是使用对象的动态特性 -> 首先执行 new 运算符. 即创建对象. 可以简单看做为 {} 的简写, var p = new ... ‘相当于‘ var p = {} -> 调用构造器. 并隐含一个参数, 即刚刚创建的对象. -> 在构造器中使用 this 引用刚刚创建出来的对象. -> 构造器结束是 默认返回 this
  • 补充说明 -> 构造器的名字, 一般使用 Pascal 命名规则( 首字母大写的 ) -> 一般为了与其他面向对象的编程语言( C++, C#, Java )保持一致. 称构造函数名为类名
      function Person( name, age, gender ) {
          this.name = name;
          this.age = age;
          this.gender = gender;
      }
      // 调用构造器创建对象
      var p = new Person( ‘jepson‘, 19, ‘男‘ );
    

异常与捕获

  • 异常:简单的说, 就是代码在执行过程中出现的错误. 并不是代码的语法错误。一旦出现异常, 其后的代码, 不再执行。
  • try catch 语法 1) try-catch 形态
      try {
          代码
      } catch ( e ) {
          代码
      }
    

    2) try-catch-finally 形态,后台用的比较多一点,主要用于释放资源,js 不是很常用

          // 例如: 将页面中第一个 a 标签的 href 设置值,但是没有 这个标签时,会出错
          try {
              var list = document.getElementsByTagName( ‘a‘ );
              list[ 0 ].href = ‘123‘;
              console.log( 2 );
          } catch ( e ) {
              console.log( ‘e: ‘ + e );    // e: TypeError: Cannot set property ‘href‘ of undefined
              console.log( 3 );
          } finally {
              console.log( 5 ); // 无论是否出现异常, try 语法结束的时候都要执行 finally 中的代码
          }
          console.log( 4 );
    
  • 自定义抛出异常 一般可以封装函数完成特定的功能
          try {
              var age = 15;
              if ( age < 18 ) {
                  throw { ‘info‘: "未满十八岁" };
              }
              console.log(‘已满十八岁‘);
          } catch ( e ) {
              console.log( e );    // { ‘info‘: "未满十八岁" }
              console.log( e.info );    // "未满十八岁"
          }
    
  • 抛出异常的语法 throw 对象 throw { name:‘jepson‘, age:18 }
时间: 2024-08-05 22:47:37

面向对象笔记一的相关文章

JS面向对象笔记二

菜单导航,<JS面向对象笔记一>,  参考书籍:阮一峰之<JavaScript标准参考教程> 一.构造函数和new命令 二.this关键字 三.构造函数和new命令 四.构造函数和new命令 五.构造函数和new命令 六.构造函数和new命令 七.构造函数和new命令 八.构造函数和new命令 一.构造函数和new命令 1.构造函数 JavaScript语言的对象体系,不是基于"类"的,而是基于构造函数(constructor)和原型链(prototype) 为

Java面向对象笔记3

Java类必须包含一个或一个以上的构造器,使用构造器最大的好处就是在创建对象时,对类的Field进行初始化(当创 建一个对象的时候,系统为这个对象的Field进行默认初始化,如果是基本类型如数值型赋值为0,如果是引用类型的 Field赋值为null),如以下代码: public class Teacher { private String name; private int age; public Teacher(){ } public Teacher(String name,int age){

Java面向对象笔记5

封装.继承.多态是面向对象的三大特征,继承是实现类重用的重要手段,但是继承会带来一个最大的坏处,那就是破坏 封装.因此接下来介绍组合,组合是实现类重用的重要方式,能提供更好的封装性. 子类扩展父类的时候,可以从父类那里继承得到Field和方法,假设现在我们有足够的权限,那么子类就可以直接复用父 类的Field和方法,但继承在带来高度复用的同时,也带来了一个严重的问题,继承严重的破坏了父类的封装性.在封装 时,我们应该遵守这个原则:每个类都应该封装它内部信息和实现细节,而只暴露必要的方法给其他类使

PHP面向对象笔记解析

PHP的面向对象是很重要的内容,也是很常用的内容.所以现在就把PHP面向对象进行整理了一下. 顺带,我会在后面把我整理的一整套CSS3,PHP,MYSQL的开发的笔记打包放到百度云,有需要可以直接去百度云下载,这样以后你们开发就可以直接翻笔记不用百度搜那么麻烦了.  笔记链接:http://pan.baidu.com/s/1qYdQdKK 密码:pvj2 一.面向对象的基本概念 1.什么是面向对象? 对象 面向 由于目前都还没有一个统一的概念,所以所能理解的就是一个物体被抽象出来,每个物品都是一

面向对象笔记基础

面向对象基础笔记 面向过程 面向对象 类的初步理解 __init__方法的理解 区分类的属性与对象的属性 继承:派生 组合 抽象类 多态与多态性 封装: 类和对象的隐藏属性 面向过程 核心是过程,即解决问题的步骤,比如设计一条流水线, 是机械的思维方式. 优点: 将复杂的问题流程化,进而简单化; 缺点: 可扩展性差; 面向对象 对象就是属性与方法的结合体. 优点: 可扩展性强; 缺点: 编程复杂度高; 应用场景:应对客户不停变化的需求,尤其是互联网应用,游戏和企业内部的应用. 类的初步理解 类是

Java面向对象笔记8

如果将一个类放在另一个类内部,那这个类就被称为内部类,内部类的主要作用如下: 1.内部类提供了更好的封装,可以把内部类隐藏在外部类之内,不允许同一个包中的其他类访问该类. 2.内部类成员可以直接访问外部类的私有数据,因为内部类被当成其外部类成员,同一个类的成员之间可以互相 访问.但外部类不能访问内部类的实现细节,例如内部类的成员变量. 3.匿名内部类适合用于创建那些仅需要一次使用的类. 成员内部类被分为两种:静态内部类和非静态内部类,使用static修饰的成员内部类是静态内部类,没有使用stat

Java面向对象笔记4

封装.继承.多态是面向对象的三大特征,在Java中什么是多态? Java引用变量有两种类型,分别是编译时类型和运行时类型.何为编译时类型,编译时类型就是由声明该变量时使用的类型决定,而运行时类型是由实际赋给该变量的对象决定 的,也就是说如果编译时类型和运行时类型不一致时,就可能出现上面提到的多态. 我们看下下面的程序: class BaseClass { public String name = "BaseClass"; public void base() { System.out.

java面向对象笔记

------Java培训.Android培训.iOS培训..Net培训.期待与您交流! ------- 1.面向对象时一种思想,将功能封装进对象,强调具备了功能的对象 2.面向对象三个特征: 封装.继承.多态.  找对象,建立对象,使用对象,维护对象之间的关系 3.类和对象的关系: 类就是对现实生活中事物的描述,是对具体的抽象 对象是这类事物实实在在的个体,具体对象是对应java在堆内存中用new建立的实体 属性对应类中的变量,行为对应类中的函数(方法),共同成为类中的成员(成员变量,成员方法)

面向对象笔记

类的特性: a.封装 1.防止数据被随意修改  2.使外部程序不需要关注对象内部的构造,只需要通过对象,对外提供的接口进行直接访问即可 b.继承 1.子类通过继承父类的方式,以最小代码量的方式,实现不同角色的共同点,和不同点 2.多继承时,继承顺序的区别  其中python2 就是深度查询,python3就是广度查询 C.多态 pass 什么是类? 其实类就是一个函数的集合即 class 类: def 函数1(): pass def 函数2(): pass 对象=类() #这就是实例化的过程 对