1.1-面向对象三大特征介绍
a.封装:将某个具体功能封装在对象中,只对外部暴露指定的接口,外界在使用的时候,只考虑接 口怎么用,不用考虑内部怎么实现(前面学习的api其实就是一种封装思想)
b.继承:一个对象拥有其他对象的属性和方法
c.多态:一个对象在不同情况下的多种状态
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<script>
/*面向对象三大特征
a.封装:将某个具体功能封装在对象中,只对外部暴露指定的接口,外界在使用的时候,只考虑接口怎么用,不用考虑内部怎么实现
b.继承:一个对象拥有其他对象的属性和方法
c.多态:一个对象在不同情况下的多种状态
*/
/*多态(了解即可,使用不多):一个对象在不同情况的多种状态
饲养员对象Person : 给动物对象喂养食物 funtion work(animal,food){ animal.eat(food) }
动物对象Animal : 吃东西 eat(food){ }
多态 : 给不同的动物喂养食物,虽然都是调用eat()方法,但是不同的动物会执行不同的eat()
*/
//示例:饲养员给动物喂食物
//动物
function Animal ( name ) {
this.name = name;
};
//猫
let cat = new Animal('猫咪');
cat.eat = function ( food ) {
console.log ( "喵喵猫" + "我吃了" + food );
};
//狗
let dog = new Animal('小狗狗');
dog.eat = function ( food ) {
console.log ( "汪汪汪" + "我吃了" + food );
};
//饲养员
function Person ( name ) {
this.name = name;
};
Person.prototype.work = function (animal,food ) {
//animal接收一个由Anmiaml构造函数生成的实例化对象,调用它的eat方法
//同一对象表现出来不同的状态,就叫做多态
animal.eat(food);
};
let p1 = new Person('ikun');
p1.work(cat, '饼干');
p1.work(dog, '翔');
</script>
</body>
</html>
1.2-继承的三种实现方式
-
继承:让一个对象拥有另一个对象的属性和方法
-
知识点
-
1.混入式继承 : 遍历 父对象 的所有属性值,添加给 子对象
-
特点:每继承一次,就要执行一次循环
-
应用场景:单个对象继承
-
-
2.替换原型继承 : 将 父对象 作为 子对象构造函数的原型
-
特点:会丢失原型之前的成员变量
-
应用场景:多个对象继承
-
-
3.混合式继承 : 混入式 + 替换原型
-
特点 : 遍历 父对象 所有的属性值,添加给 子对象构造函数 的原型
-
-
1.混入式继承
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<script>
/*学习目标 : 继承的三种实现方式
1.混入式继承 : 遍历 父对象 的所有属性值,添加给 子对象
特点:每继承一次,就要执行一次循环
应用场景:单个对象继承
2.替换原型继承 : 将 父对象 作为 子对象构造函数的原型
特点:会丢失原型之前的成员变量
应用场景:多个对象继承
3. 混合式继承 : 混入式 + 替换原型
特点 : 遍历 父对象 所有的属性值,添加给 子对象构造函数 的原型
*/
//继承:让一个对象拥有另一个对象的属性和方法
let father = {
house:{
address:'北京一环',
price:100000000
},
car:{
brand:'劳斯莱斯',
price:5000000
}
}
let son = {
name:'ikun',
age:30
}
//1.混入式
//解决方案:遍历父对象的所有属性值,添加给子对象
//特点:每继承一次,就要执行一次循环
//应用场景 : 单个对象继承
for (let key in father){
father[key] = son[key]
}
console.log ( son )
</script>
</body>
</html>
2.替换原型继承
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
</head>
<body>
<script>
//2.替换原型
//解决方案:将父对象作为子对象构造函数的原型
//特点:会丢失原型之前的成员变量
//应用场景:多个对象继承
let father = {
house:{
address:'北京一环',
price:100000000
},
car:{
brand:'劳斯莱斯',
price:5000000
}
}
function Son (name,age ) {
this.name = name
this.age = age
}
Son.prototype.sayHi = function(){
console.log('你好')
}
//让父对象成为子对象构造函数的原型
Son.prototype = father
//实例化对象
let son1 = new Son('ikun',30)
console.log ( son1 )
let son2 = new Son('班长',20)
console.log ( son2 )
</script>
</body>
</html>
3.混合式继承
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
</head>
<body>
<script>
/*学习目标 : 继承的三种实现方式
1.混入式继承 : 遍历 父对象 的所有属性值,添加给 子对象
特点:每继承一次,就要执行一次循环
应用场景:单个对象继承
2.替换原型继承 : 将 父对象 作为 子对象构造函数的原型
特点:会丢失原型之前的成员变量
应用场景:多个对象继承
3. 混合式继承 : 混入式 + 替换原型
特点 : 遍历 父对象 所有的属性值,添加给 子对象构造函数 的原型
*/
//3. 混合式(混入+替换原型)
//解决方案:遍历父对象所有的属性值,添加给子对象构造函数的原型
let father = {
house:{
address:'北京一环',
price:100000000
},
car:{
brand:'劳斯莱斯',
price:5000000
}
}
function Son (name,age ) {
this.name = name
this.age = age
}
Son.prototype.sayHi = function(){
console.log('你好')
}
//将父对象的所有属性添加到子对象构造函数的原型中
for(let key in father){
Son.prototype[key] = father[key];
}
//实例化对象
let son1 = new Son('ikun',30)
console.log ( son1 )
let son2 = new Son('班长',20)
console.log ( son2 )
</script>
</body>
</html>
02-原型链
==1.1-原型链介绍==
-
知识点
-
1.原型链:每一个对象都有原型,原型本身又是对象,所以原型又有原型,以此类推形成一个链式结构,称为原型链
-
2.对象访问原型链中的成员规则:就近原则
-
当访问一个对象的成员变量时,会首先访问它自身的成员变量,如果有则访问。没有则在原型中寻找,能找到就访问,不能找到则继续往原型的原型中寻找,以此类推,如果找到原型链的顶端还是找不到,则程序报错:
xxx is not a function
-
-
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
</head>
<body>
<script>
/*
1.原型链 :每一个对象,都有__proto__指向自身的原型。 而原型也是对象,也有自己的
__proto__指向原型的原型,以此类推形成链式结构,称之为原型链。
2.对象访问原型链中成员的规则 :就近原则
当访问对象的成员,先看自己有没有。有则访问,没有则看原型有没有。原型有则访问,
没有则访问原型的原型,没有则继续往上找。以此类推,一直找到原型链终点 : null.
还没有, 如果是属性 : 则获取undefined 如果是方法 ,则报错xxx is not defined
*/
//1.构造函数
function Person(name,age){
this.name = name;
this.age = age;
};
//2.原型对象
Person.prototype.sayHi = function(){
console.log('人生若只如初见,何事秋风悲画扇');
};
Person.prototype.type = '哺乳动物';
//3.实例化对象
let p1 = new Person('又又',18);
console.log(p1);
//请说出以下代码执行结果
console.log(p1.name);//又又 p1自己有name属性
console.log(p1.type);//哺乳动物 p1自己没有type,但是p1的原型有
console.log(p1.hobby);//undefined p1自己没有hobby,原型也没有
p1.sayHi();// 人生若只如初见,何事秋风悲画扇 p1自己没有这个方法,原型有
// p1.eat();//报错 xxx is not defined p1自己没有这个方法,原型也没有
//为什么不报错? p1自己没有这个方法,原型也没有这个方法,但是原型的原型有
p1.toString();
//查看p1的原型链
console.log(p1.__proto__.constructor);//Person
console.log(p1.__proto__ === Person.prototype);//true
//查看p1的原型的原型
console.log(p1.__proto__.__proto__.constructor);//Object
console.log(p1.__proto__.__proto__ === Object.prototype);//true
//查看p1的原型的原型的原型
console.log(p1.__proto__.__proto__.__proto__);//null
</script>
</body>
</html>
1.2-原型链详解:内置对象的原型链
-
知识点:内置对象的原型链
-
1.查看Array的原型链
-
构造函数的原型本身是一个对象,只要是对象就有原型
-
-
2.查看Date的原型链
-
所有的内置对象(Math Array 基本包装类型等)的原型链都是一样的,最终都指向Object
-
-
3.查看String的原型链:了解这里的String值得是内置对象String(是一个基本包装类型),其他的Number、Boolean原型链和String是一样的
-
只有对象才有原型,这里一定要把基本数据类型string、number、boolean,和基本包装类型(特殊的引用类型对象)String、Number、Boolean区分开来,不要搞混淆
-
-
1.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
2-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
3-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
4-DOM对象原型链
//4.界面元素
let div1 = document.getElementById('div1');
let p1 = document.getElementById('p1');
-
完整代码
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div id="div1"></div>
<p id="p1"></p>
<script>
/*查看内置对象的原型链*/
//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
//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
//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
//4.界面元素
let div1 = document.getElementById('div1');
let p1 = document.getElementById('p1');
</script>
</body>
</html>