js-----面向对象(三)

114 阅读3分钟

现实中的面向对象

  • 对象 万物皆对象 每个对象都与自己的属性(公有属性 私有属性)
  • 类 抽象对象的特点和功能 形成描述一类事物的抽象概念 在js中分为内置类和自定义类
  • 实例 类中的一个具体的个体 只要是类中的个体就会有这个类型全部属性和特点

JS中的面向对象 继承 封装 多态(重写 冲载)

  1. 类 JS中的类都是一个函数数据类型 都天生自带一个prototype属性 它的值是一个对象
  2. prototype(原型) 每一个prototype对象都有天生自带一个属性constructor 这个属性的值 指向当前类的构造函数本身
  3. 对象(实例对象 prototype对象)都有一个__proto__的属性 这个属性的值指向当前实例所属类的prototype

内置类 Array String Number Funtcion Date等

内置类的原型: 每个类都有自己的原型 存储这个类型公有的属性和方法

  • 数组的原型 push pop slice 等
  • Date的原型 getFullYear getMonth getHours 等
  • String的原型 chartAt charCodeAt toUpperCase 等

自定义类型 通过自定义类型构造函数

  • 定义一个构造函数 就是创建一个类
  • 给这个类的原型上添加这个类的公有属性
  • 创建类的实例

检测是否是私有属性 hasOwnProperty()

重写 子类改写父类上的属性和方法

重载: 根据不同的函数签名自动调用不同的方法 js没有真正意义上的重载

原型链 : 原型链:对象.属性名 (obj.xxx) 先看私有属性是否有这样是一个属性,如果私有属性中没有,根据实例对象的 proto 找到当前对象所属类的原型查找,如果原型上也没有,就通过原型对象 proto 继续向上查找; 一直找到 Object.prototype 如果也没有就返回 undefined

原型上添加公有属性

  1. 直接给原型添加方法
fn.prototype.name = 'zhangsan'
  1. 通过实例对象的__proto__
let f1 = new fn();
f1.__proto__.name = 'zhangsan';
  1. 修改原型对象的指向
Fn.prototype.constructor = Fn;
// 当需要批量给原型增加属性或者方法时,我们需要把一个新的对象赋值给类的原型时,此时要给这个对象增加一个 constructor 属性

选项卡封装

// 1. 创建选项卡类
function Tab(options) {
  // 1. 确保如何是通过 new 操作调用
  if (!(this instanceof Tab)) {
    console.error('Tab is a constructor which should be call with new');
    return;
  }

  // 2. 参数合法校验
  if (!options || !options.el) {
    console.error('缺少el元素');
    return;
  }

  // 3. 将传进来的参数对象保存到实例上
  this._options = options;

  // 4. 执行初始化
  this.init();
}



// 为 tab 增加 init 方法:
Tab.prototype.init = function () {
  this.queryEle();
  this.bindEvent();
};

// 为 Tab 增加公用的获取元素的方法
Tab.prototype.queryEle = function () {
  // 1. 从 this 中的 options 中的 el 获取最外层元素
  const container = document.querySelector(this._options.el);

  // 2. 获取选项卡头,并挂载到实例上
  this.headerList = container.querySelectorAll('.header > li');

  // 3. 获取所有的卡片并挂载到实例上
  this.cardList = container.querySelectorAll('div');
};

// 为Tab增加公用的绑定事件的元素
Tab.prototype.bindEvent = function () {
  const HEADER_LIST = this.headerList; // 用一个常量缓存 headerList
  // 变量 headerList 给每个 li 绑定点击事件
  for (let i = 0; i < HEADER_LIST.length; i++) {
    HEADER_LIST[i].onclick = () => {
      // 这里使用箭头函数,是因为我们希望这里的 this 是 Tab 的实例,如果不使用箭头函数,点击事件函数中的 this 就是选项卡头了
      this.clearClass();
      this.addClass(i);
    }
  }
};

// 为 Tab 类增加移除类名的方法
Tab.prototype.clearClass = function () {
  const HEADER_LIST = this.headerList;
  const CARD_LIST = this.cardList;
  for (let i = 0; i < HEADER_LIST.length; i++) {
    HEADER_LIST[i].className = '';
    CARD_LIST[i].className = '';
  }
};

// 为 Tab 类添加类名的方法
Tab.prototype.addClass = function (index) {
  this.headerList[index].className = 'active';
  this.cardList[index].className = 'active';
};

new Tab({
  el: '#tab1'
});

new Tab({
  el: '#tab2'
});