现实中的面向对象
- 对象 万物皆对象 每个对象都与自己的属性(公有属性 私有属性)
- 类 抽象对象的特点和功能 形成描述一类事物的抽象概念 在js中分为内置类和自定义类
- 实例 类中的一个具体的个体 只要是类中的个体就会有这个类型全部属性和特点
JS中的面向对象 继承 封装 多态(重写 冲载)
- 类 JS中的类都是一个函数数据类型 都天生自带一个prototype属性 它的值是一个对象
- prototype(原型) 每一个prototype对象都有天生自带一个属性constructor 这个属性的值 指向当前类的构造函数本身
- 对象(实例对象 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
原型上添加公有属性
- 直接给原型添加方法
fn.prototype.name = 'zhangsan'
- 通过实例对象的__proto__
let f1 = new fn();
f1.__proto__.name = 'zhangsan';
- 修改原型对象的指向
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'
});