前言
JavaScript:是一门;而面向对象是一种;是根据需求来一步一步完成任务的一种思想。
什么是对象?
--- 指的是 属性 和 方法 的集合体。
- 属性:储存数据;
- 方法:执行的动作。
什么是键值对?
语法: obj = {
name:12,
age:13,
skill:function(){}
}
* name,age: 表示对象obj的属性名,冒号后面的为属性值,像这种形式我们叫 ***键值对*** 。
* skill: 是obj对象的方法。
自定义对象(5种):
1、字面量:
- 优点:简单,容易理解
- 缺点:不能批量生产
语法:
//1.字面量定义对象:
var obj = {
name:"超人",
age:27,
skill:function(){
console.log("激光波");
}
}
console.log(obj.name);//超人 --- 调用 (属性)的语法
console.log(obj["name"]);//超人 --- 另一种调用 (属性)的语法,注意语法要加上双引号!
obj.skill();//激光波 --- 调用 (方法)的语法
2、工厂模式:
- 优点:实现了对象的批量生产
- 缺点:不能检测出对象是由谁来产生的。
语法:
//2.工厂模式:
function factory(name,age,callback){
return {
name:name,
age:age,
skill:function(){
console.log("睡觉zZ")
},
callback:callback
}
}
var girlfriend = factory("翠花",18);
console.log(girlfriend);//{name: "翠花", age: 18, skill: ƒ, callback: undefined}
var girlfriend2 = factory("如花",81);
console.log(girlfriend2);//{name: "如花", age: 81, skill: ƒ, callback: undefined}
console.log(girlfriend == girlfriend2);//false //---因为是两个是独立的对象
//测试增加回调函数
var girlfriend3 = factory("凤姐",20,function(){
console.log("蛋炒饭!");
})
console.log(girlfriend3);//{name: "凤姐", age: 20, skill: ƒ, callback: ƒ}
girlfriend3.callback(); //调用里面的函数
//缺点:
console.log(girlfriend3 instanceof Object);//true //--- 可是不能检测出对象是由谁来产生的
console.log(girlfriend3.prototype);//undefined //---prototype只能用于函数,而这是对象
3、构造函数模式:
--- 所有属性和方法需要通过this来定义,通过new关键词进行调用。
优点:解决不能识别 其是由谁创建出来的问题。
-
缺点:实现相同的方法,但是却会各自创建新的空间来存放这些方法。这样会造成空间浪费!
拓展 : new关键词做了什么事? * 1、创建一个新对象 * 2、将this指向新对象 * 3、执行构造函数的代码 * 4、返回这个 *新对象*
语法:
//3.构造函数:
function Human(type,name,gender,age){
this.type = type;
this.name = name;
this.gender = gender;
this.age = age;
this.skill = function(){
console.log("走");
}
}
var pangu = new Human("黄种人","盘古","男","20");
console.log(pangu);//Human {type: "黄种人", name: "盘古", gender: "男", age: "20", skill: ƒ}
var xiawa = new Human("白种人","夏娃","女","1000");
console.log(xiawa);//Human {type: "白种人", name: "夏娃", gender: "女", age: "1000", skill: ƒ}
console.log(xiawa.prototype);//undefined //---prototype 对 对象不可用
console.log(xiawa.constructor);//Human(type,name,gender,age){..
console.log(xiawa.__proto__);//{constructor: ƒ}
//缺点:
console.log(pangu.skill == xiawa.skill);//false
//--- 说明两个对象不是指向同一个空间,而是各创建一次对象,也就创建了一次相同的方法,这样会造成了资源空间浪费!
4、原型模式:
- 优点:实现继承,解决了构造函数空间浪费问题
- 缺点:不能定制
语法:
//4、原型模式:--- 用于解决继承问题
function Animal(){};
Animal.prototype.type = "猫";
Animal.prototype.skill = function(){
console.log("吃吃吃--")
}//固定写一个属性,不可定制!
var mao = new Animal();
mao.skill();//吃吃吃--
var mao2 = new Animal();
console.log(mao.skill == mao2.skill);//true //---说明两个对象指向同一个空间,是继承过来的。
console.log(mao)//Animal {} //--- 说明mao自身没有skill方法
console.log(mao.__proto__)//{type: "猫", skill: ƒ, constructor: ƒ} //---
console.log(mao == mao2);//false //--- 说明每次new出来的都是独立的新对象
console.log(mao.type == mao2.type);//true //---说明对象属性指向相同
5、混合模式:
--- 构造函数模式和原型模式的结合。
- 优点:
- 缺点:
语法:
//5、混合模式:
function Student(cls,name,age,gender,number){
this.cls = cls;
this.name = name;
this.age = age;
this.gender = gender;
this.number = number;
}
Student.prototype.skill = function(){
console.log("学习");
}
var student1 = new Student("01","小芳",12,"女","0101");
console.log(student1);//Student {cls: "01", name: "小芳", age: 12, gender: "女", number: "0101"} //--- 这里没有skill
var student2 = new Student("01","小蓝",12,"女","0101");
console.log(student2);//Student {cls: "01", name: "小芳", age: 12, gender: "女", number: "0101"} //--- 这里没有skill
console.log(student1 == student2)//false //---说明都是独立的个体
console.log(student1.skill == student2.skill)//true //---说明都是继承父级的方法
/*注意*/
console.log(student1.age == student2.age)//true //---这里返回的是简单数据类型,直接比较值
6、class类定义对象:
6.1、语法:
class name{
constructor( ){
相当于混合模式的构造函数
}
放在constructor外面的方法或者是属性(这个位置的代码相当于混合模式中的原型对象上的方法)
}
6.2、如何实现类与类之间的继承?
--- 可以通过extends关键字来实现:
语法(比如类B需要继承类A):
class A{ };
class B extends A{
constructor( ){
super( )//调用类A
}
};
语法:
//6、class类实现选项卡:
class Tab{
constructor(){}//没有的话可以省略 ***
init(){
var leng = this.btns.length;
var that = this;
for(var i=0;i<leng;i++){
this.btns[i].index = i;
this.btns[i].addEventListener("click",function(){
for(var j=0;j<leng;j++){
that.content[j].style.display = "none";
}
that.content[this.index].style.display = "block";
})
}
}
}
class Tabchild extends Tab{
constructor(el){
super();//调用
this.el = document.querySelector(el);//获取到选项卡最大的容器
this.btns = this.el.querySelector(".btns").children;//获取所有按钮
this.content = this.el.querySelector(".content").children;//获取内容
}
}
var tab = new Tabchild(".tab");
tab.init();