目录
面向对象三大特征介绍
1.封装:将某个具体功能封装在对象中,只对外部暴露指定的接口,外界在使用的时候,只考虑接口怎么用,不用考虑内部怎么实现
2.继承:一个对象拥有其他对象的属性和方法
3.多态:一个对象在不同情况下的多种状态
封装:将某个具体功能封装在对象中,只对外部暴露指定的接口,外界在使用的时候,只考虑接口怎么用,不用考虑内部怎么实现
继承的三种实现方式
-
1.混入式继承 : 遍历 父对象 的所有属性值,添加给 子对象
-
特点:每继承一次,就要执行一次循环
-
应用场景:单个对象继承
-
-
2.替换原型继承 : 将 父对象 作为 子对象构造函数的原型
-
特点:会丢失原型之前的成员变量
-
应用场景:多个对象继承
-
-
3.混合式继承 : 混入式 + 替换原型
-
特点 : 遍历 父对象 所有的属性值,添加给 子对象构造函数 的原型
-
混入式继承
<script>
let father = {
car: {
brand: "玛莎拉蒂",
price: 8000000
},
house: {
address: '汤臣一品',
price: 100000000
}
}
let son = {
name: '聪明蛋',
age: 22
}
for (let key in father) {
son[key] = father[key]
}
console.log(son);
</script>
混入式
//解决方案:遍历父对象的所有属性值,添加给子对象
//特点:每继承一次,就要执行一次循环
//应用场景 : 单个对象继承
替换原型继承
<script>
let father = {
car: {
brand: "玛莎拉蒂",
price: 8000000
},
house: {
address: '汤臣一品',
price: 100000000
}
}
function Son(name, age) {
this.name = name
this.age = age
}
Son.prototype.eat = function () {
console.log('吃东西');
}
Son.prototype = father
let son1 = new Son('聪明蛋', 22)
let son2 = new Son('聪明蛋', 24)
console.log(son1, son2);
</script>
2.替换原型
//解决方案:将父对象作为子对象构造函数的原型
//特点:会丢失原型之前的成员变量
//应用场景:多个对象继承
混合式继承
<script>
/**
* JS继承三种方式
* 1 混入式: 遍历父对象成员,添加给子对象
特点: 单个对象继承
*2 替换原型: 父对象 作为子对象构建函数原型
特点:多个对象继承 但是会覆盖原来的默认原型
3 混合式, 混入+替换原型 遍历父对象成员 添加给子对象构建函数原型
特点:多个对象继承,不会覆盖原来的默认原型
*/
let father = {
car: {
brand: "玛莎拉蒂",
price: 8000000
},
house: {
address: '汤臣一品',
price: 100000000
}
}
function Son(name, age) {
this.name = name
this.age = age
}
Son.prototype.eat = function () {
console.log('吃东西')
}
for (let key in father) {
Son.prototype[key] = father[key]
}
let son1 = new Son('聪明蛋', 22)
let son2 = new Son('尹君君', 24)
console.log(son1, son2)
</script>
原型链
-
原型链:每一个对象都有原型,原型本身又是对象,所以原型又有原型,以此类推形成一个链式结构,称为原型链
-
2.对象访问原型链中的成员规则:就近原则
-
当访问一个对象的成员变量时,会首先访问它自身的成员变量,如果有则访问。没有则在原型中寻找,能找到就访问,不能找到则继续往原型的原型中寻找,以此类推,如果找到原型链的顶端还是找不到,则程序报错:
xxx is not a function
-
.Array的原型链
//1.Array
let arr = new Array(10,20,30);
console.log ( arr );
//查看arr的原型
console.log ( arr.__proto__.constructor );//Array
console.log ( arr.__proto__ === Array.prototype );
//查看arr的原型的原型
console.log ( arr.__proto__.__proto__.constructor );//Object
console.log ( arr.__proto__.__proto__ === Object.prototype );//true
Date的原型链
//2.Date
let date1 = new Date();
//细节:日期对象直接console.log会转成string,查看对象需要使用console.dir打印
console.dir(date1);
console.log ( date1.__proto__ === Date.prototype );//true
console.log ( date1.__proto__.__proto__.constructor );//Object
console.log ( date1.__proto__.__proto__ === Object.prototype );//true
String对象原型链
//3.String
let str = new String('123');
console.log ( str );
console.log ( str.__proto__ === String.prototype );//true
console.log ( str.__proto__.__proto__.constructor );//Object
console.log ( str.__proto__.__proto__ === Object.prototype );//true
DOM对象原型链
//4.界面元素
let div1 = document.getElementById('div1');
let p1 = document.getElementById('p1');
instanceof运算符
-
instanceof语法:
对象
instanceof
构造函数
-
作用:检测构造函数的原型prototype在不在这个对象的原型链上
class关键字
class关键字作用: 声明一个类函数
* 相当于ES5的构造函数,只是代码的阅读性大大提高
* a. 把构造函数和原型全部写在一个大括号里面,提高代码阅读性
* b. 必须要使用new才可以调用class函数,提高代码规范
1.2 class关键字语法:
class 构造函数名{
constructor(){
//(1)这里写构造函数代码
};
//(2)原型里面的方法写在下面
eat(){
};
play(){
};
};
<script>
class Person {
//1.构建函数
constructor(name, age) {
this.name = name
this.age = age
}
// 2.原型方法
speak() {
console.log('看吃播')
}
}
// 3.实例对象
let p1 = new Person('聪明蛋', 22)
console.log(p1)
</script>
extends关键字介绍
extends关键字
1.作用: 继承
2.底层原理: 替换原型继承
<script>
class Person {
//1.构建函数
constructor(name, age) {
this.name = name
this.age = age
}
// 2.原型方法
speak() {
console.log('看吃播')
}
}
class Student extends Person {
learn() {
console.log('我今天学的很扎实')
}
}
// 3.实例对象
let p1 = new Person('聪明蛋', 22)
console.log(p1)
let s1 = new Student('尹君君', 20)
console.log(s1)
s1.learn() // 调用子类自己的方法
s1.eat() // 调用父类方法 (继承了父类所有的成员)
</script>
super关键字介绍
super关键字
1.作用: 子类中调用父类的方法
2.底层原理: 函数上下文调用
<script>
class Person {
constructor(name, age) {
this.name = name
this.age = age
}
sayHi() {
console.log('聪明蛋你好啊');
}
}
class Teacher extends Person {
constructor(name, age, className) {
super(name, age)
this.className = className
}
teach() {
console.log('你在梦游')
}
}
let p1 = new Person('聪明蛋', 22)
console.log(p1);
let t1 = new Teacher('聪明蛋', 22, '高三十二班')
console.log(t1);
p1.sayHi()
t1.teach()
</script>
总结
-
1.面向对象三大特征
-
a.封装:将某个功能封装到对象或函数中
-
b.继承:一个对象拥有另一个对象的所有成员变量(属性和方法)
-
c.多态:一个对象在不同情况的多种状态
-
-
2.实现继承的几种方式
-
a.混入式继承
-
解决方案:遍历父对象的所有属性值,添加给子对象
-
弊端:每继承一次,就要执行一次循环
-
应用场景:父对象只有一个子对象
-
-
b.替换原型
-
解决方案:将父对象作为子对象构造函数的原型
-
弊端:会丢失原型之前的成员变量
-
应用场景:自定义内置对象
-
-
c.混合式(混入+替换原型)
-
解决方案:遍历父对象所有的属性值,添加给构造函数的原型
-
应用场景:父对象有多个子对象
-
-
-
3.原型链
-
原型链:每一个对象都有原型,原型本身又是对象,所以原型又有原型,以此类推形成一个链式结构,称为原型链
-
-
对象在原型链中的访问规则:就近原则
-
当访问对象成员变量时,会先从自己的属性中查找,如果有就访问,没有就访问自己原型的,如果原型中没有,则访问原型的原型,以此类推,如果访问到原型链的顶端还是没有,则程序报错
xxxx is not undefined
-
特殊情况:Object.prototype的原型对象是null
-
-
d.函数本身也是对象
-
构造函数属于函数
-
-
5.instanceof运算符
-
语法:
对象 instanceof 构造函数
-
作用:检测构造函数的原型prototype在不在这个对象的原型链上
-