![](https://img.haomeiwen.com/i4578791/9194d46823bec2a1.jpg)
一、概念
1. 什么是对象?
现实世界: 男朋友,女朋友,狗!电视,冰箱... 实际上,什么东西都是对象。
==万物皆对象==
程序世界:
Date RegExp Array ...
2. 什么是面向对象?
“看着你的对象 ^ _ ^ ”
面向对象 -> 和对象打交道,包括:使用对象,制造对象
graph LR
用对象-->方便省事
方便省事-->以前
写对象-->$$$
$$$-->现在
3. 对象的组成
-
属性:变量,有归属的变量
静态的东西,如:人的身高、体重... -
方法:函数,有归属的函数
动态的东西,如:人会跑,吃,玩... -
事件:在JS对象中和方法在一起,不单独考虑,
给对象一个动作,它的反应是什么。
let a = 12; //变量
window.a = 12; //属性
function show(){} //函数
window.show = function(){} //方法
4. 类和实例
类:模板 没有实际的功能和用途
实例:根据模板造出来的具体东西,有真正的能和用途
5. 面向对象的特征
封装: 只管使用,不用关心细节实现
继承: 子类直接使用父类的东西
多态: JS中没有
二、对象创建
对象包含:属性、方法。其创建过程就是看如果写属性,如何写方法。
(一) 属性
- 弄一个对象(其实就是通过函数)
//人,属性:姓名、年龄
function Person(name,age){
let obj = new Object();
obj.name = name;
obj.age = age;
return obj;
}
//-->使用
let p1 = Person('张三',30);
alert(p1.name);
工厂模式: 以上Person函数的实现,符合工厂模式
graph LR
原料-->加工
加工-->出厂
Object-->obj.*=x
obj.*=x-->return
2.用new弄一个对象
(以前见过的对象,Array,RegExp... 都是new出来的,我们写的对象也应该是new出来的)
let p1 = new Person('张三',20);
注意:使用 new 后,Person函数中的写法有变化
- new Person 后,函数中自动new Object(),并赋值给this,自动返回this.
function Person(name,age) {
this.name = name;
this.age = age;
}
let p1 = new Person('张三',30);
alert(p1.name);
构造函数:以上Person,是函数,这种方法(用于new一个对象时),又叫‘构造函数’,构造函数约定——首字母大写。
能new出的东西,本质都是函数,只不过有个名字叫做——构造函数。
new一个类的实例,构造函数自动执行。
(二) 方法
类(模板、模子)身上有一个属性,叫:原型 prototype。 方法,就存在类的原型身上。
方法就是函数,有归属的函数。
‘给Person加显示名字和年龄的方法’
function Person(name,age) {
this.name = name;
this.age = age;
}
Person.prototype.showName = function() {
alert(this.name);
}
Person.prototype.showAge = function() {
alert(this.age);
}
let p1 = new Person('张三',30);
p1.showName();
p1.showAge();
原型的方法在类身上,没有在实例身上
三、继承
父类有什么,子类也有什么——父级的东西,也是子级的
上面实现了Person类,现在需要一个工人类Worker,有几种方式,如下:
- 什么都不管,从0开始写Worker类,可以实现,但是不是很好,因为工人也是人,人拥有的属性和方法同样适用于工人,不能碰到一类人就从头开始;
- 把Person类直接改成Worker,不可行,因为原来已经存在使用Person类的代码了;
- 把Person直接复制一遍,进行修改,也不好,如果Person类有修改,按照常规说所有的人都要改,但这种方式下,Worker就修改不了了;
- 最好的办法就是继承;√
继承要实现几件事:
- 父类有的东西,子类自然具备 ——天经地义
- 子类不能对父类产生影响
- 父类有修改,子类自动跟着变
继承,到底要继承什么?
- 父类的属性
- 父类的方法
(一) 属性的继承
方法:在子类的构造函数里调用父类的构造函数——注意this
function Worker(name,age,job) {
// 1.继承父类的属性
Person(name,age);
// 2.添加子类自己的属性
this.job = job;
}
let w1 = new Worker('李四',20,'工人');
在以上代码中,Person中的this出现了问题,期望,在new Worker的时候,this能够指向Worker这个对象——解决办法:call,apply。
1、fn.call():强制改变this的指向:
function Worker(name,age,job) {
Person.call(this,name,age);
}
2、fn.apply():同样用于改变this指向,和call的语法不同:
Person.apply(this,[name,age]);
Person.apply(this,arguments);
(二) 方法的继承
方式:
1.Worker.prototype = Person.prototype; ×引用,改变子类时会影响父类
2.Worker.prototype = new Person(); √Person的实例可以完全使用Person类的方法(showName,showAge...)
(三) 关于类型检查
1.typeof:适用于基本类型
2.instanceof:是不是某个类的实例,一直包括父级
3.constructor:到底是由谁构造出来的
// -- typeof
let a = 12;
let arr = [1,2,3,4];
let oDate = new Date();
alert(typeof a); // number
alert(arr); // object
alert(json); // object
// 用typeof 无法区分 arr 和 json
// --instanceof
alert(arr instanceof Array); // true
alert(oDate instanceof Date); // true
alert(arr instanceof Date); // false
alert(oDate instanceof Object); // true
alert(arr instanceof Object); // true
// -- 一切都是对象,Object是所有对象的父类,这个是可以理解的,但是,到底是谁构造出来的?亲爹是谁?我们来看一下constructor
// -- constructor
alert(oDate.constructor == Date); // true
alert(arr.constructor == Array); //true
alert(oDate.constructor == Array); // false
基本类型,有些特殊
let a = 12;
alert(a instanceof Number); // ×,基本类型不是对象
// 基本类型可以包装成对象
let a = new Number(12);
alert(a instanceof Number); // true
基本类型与包装类型的对应
1.number => Number
2.string => String
3.boolean =>Boolean
4.undefined => Undefined? // 大家可以测一下这个
JS中,包装类型没什么用
除基本类型外,所有东西都属于Object
(四)总结:写一个对象,继承完整的步骤
1.写父类 属性在 —— 构造函数里,方法 —— 在原型上prototype
2.写子类
1)属性的继承 —— 在子类的构造函数里通过父类的构造函数.apply/.call
2)方法的继承 —— 子类的prototype = new 父类的构造函数
3)指定一下子类的构造函数 子类.prototype.construcor = 子类的构造函数
如果一个对象归属于子类,那么它同时也归属于子类的父类
人-->警察
人-->老师
人-->小偷
警察-->武警
警察-->片警
警察-->交警
片警-->张三
张三是片警,也是警察,也是人
原型链:调用某种属性或方法时,先看看自己有没有,自己没有找父级,一直向上直到 Object
用原型,可以拓展系统方法,但是要注意,优先用系统的
Array.prototype.indexOf = Array.prototype.indexOf || function() {}
四、ES6面向对象
(一) 类的定义
class Person {
// 构造函数
constructor(name,age) {
this.name = name;
this.age = age;
}
showName() {
alert(`我叫${this.name}`)
}
showAge() {
alert(`我今年${this.age}`)
}
}
let p1 = new Person("李四",20);
p1.showName();
p1.showAge();
(二) 继承
class Worker extends Person {
constructor(name,age,job) {
super(name,age);
this.job = job;
}
showJob(){
alert(`我的工作的${this.job}`)
}
}
super: 超类:可以用在类的继承中,或者对象字面量中,super指代了整个prototype或者proto指向的对象
面向对象暂时先介绍到这里,之后再补充~
网友评论